finding the word at a position in javascript

前端 未结 6 2062
慢半拍i
慢半拍i 2020-12-10 06:18

For string input of \'this is a sentence\' it must return \'is\' when position is 6 or 7. When position is 0, 1, 2, 3 or 4 result must be \'this\'.

What is the easie

相关标签:
6条回答
  • 2020-12-10 07:01
    function getWordAt(s, pos) {
      // make pos point to a character of the word
      while (s[pos] == " ") pos--;
      // find the space before that word
      // (add 1 to be at the begining of that word)
      // (note that it works even if there is no space before that word)
      pos = s.lastIndexOf(" ", pos) + 1;
      // find the end of the word
      var end = s.indexOf(" ", pos);
      if (end == -1) end = s.length; // set to length if it was the last word
      // return the result
      return s.substring(pos, end);
    }
    getWordAt("this is a sentence", 4);
    
    0 讨论(0)
  • 2020-12-10 07:05
    function getWordAt(str, pos) {
    
       // Sanitise input
       str = str + "";
       pos = parseInt(pos, 10);
    
       // Snap to a word on the left
       if (str[pos] == " ") {
          pos = pos - 1;
       }
    
       // Handle exceptional cases
       if (pos < 0 || pos >= str.length-1 || str[pos] == " ") {
          return "";
       }
    
       // Build word
       var acc = "";
       for ( ; pos > 0 && str[pos-1] != " "; pos--) {}
       for ( ; pos < str.length && str[pos] != " "; pos++) {
          acc += str[pos];
       }
    
       return acc;
    }
    
    alert(getWordAt("this is a sentence", 6));
    

    Something like this. Be sure to thoroughly test the loop logic; I didn't.

    0 讨论(0)
  • 2020-12-10 07:07
    function getWordAt (str, pos) {
    
        // Perform type conversions.
        str = String(str);
        pos = Number(pos) >>> 0;
    
        // Search for the word's beginning and end.
        var left = str.slice(0, pos + 1).search(/\S+$/),
            right = str.slice(pos).search(/\s/);
    
        // The last word in the string is a special case.
        if (right < 0) {
            return str.slice(left);
        }
    
        // Return the word, using the located bounds to extract it from the string.
        return str.slice(left, right + pos);
    
    }
    

    This function accepts any whitespace character as a word separator, including spaces, tabs, and newlines. Essentially, it looks:

    • For the beginning of the word, matched by /\S+$/
    • Just past the end of the word, using /\s/

    As written, the function will return "" if the index of a whitespace character is given; spaces are not part of words themselves. If you want the function to instead return the preceding word, change /\S+$/ to /\S+\s*/.


    Here is some example output for "This is a sentence."

    0: This
    1: This
    2: This
    3: This
    4:
    5: is
    6: is
    7:
    8: a
    9:
    10: sentence.
    // ...
    18: sentence.
    

    Modified to return the preceding word, the output becomes:

    0: This
    1: This
    2: This
    3: This
    4: This
    5: is
    6: is
    7: is
    8: a
    9: a
    10: sentence.
    // ...
    18: sentence.
    
    0 讨论(0)
  • 2020-12-10 07:07

    I had some strange behavior in the most popular answer at time of writing with getting the word if the position is at the last character of a word that isn't the last word.

    Here's my rendition:

    • Instead of returning the word, I return the indices of the bounds of the word for more flexibility.
    • I use regular expressions for detecting whitespace, since the list of whitespace is quite large, varies under different locales, and is still relatively performant because only 1 character is checked.
    • Note: When the character at position and position-1 are at a space, the function returns [position, position]. This makes sense actually because the position does not have a word.
    function getWordBoundsAtPosition(str, position) {
      const isSpace = (c) => /\s/.exec(c);
      let start = position - 1;
      let end = position;
    
      while (start >= 0 && !isSpace(str[start])) {
        start -= 1;
      }
      start = Math.max(0, start + 1);
    
      while (end < str.length && !isSpace(str[end])) {
        end += 1;
      }
      end = Math.max(start, end);
    
      return [start, end];
    }
    

    To plug into substring, just deconstruct the returned bounds.

    const myString = 'This is a sentence.';
    const position = 7;
    
    const wordBoundsAtPosition = getWordBoundsAtPosition(myString, position);
    const wordAtPosition = myString.substring(...wordBoundsAtPosition); // => 'is'
    

    Cool Visualization

    I created a visualization of where the bounds returned by this method are in your string below:

    function getWordBoundsAtPosition(str, position) {
      const isSpace = (c) => /\s/.exec(c);
      let start = position - 1;
      let end = position;
    
      while (start >= 0 && !isSpace(str[start])) {
        start -= 1;
      }
      start = Math.max(0, start + 1);
    
      while (end < str.length && !isSpace(str[end])) {
        end += 1;
      }
      end = Math.max(start, end);
      
      return [start, end];
    }
    
    function analyzeStringWithCursor(str, bounds, cursorIdx) {
      document.getElementById("analysis").innerText = `
     ${"0123456789".repeat(Math.floor((str.length - 1) / 10) + 1)}
     ${str}
    ${" ".repeat(bounds[0])}↗${" ".repeat(bounds[1] - bounds[0])}↖
    Cursor: ${cursorIdx}
    getWordBoundsAtPosition("${str}", ${cursorIdx}): ${JSON.stringify(bounds)}
    substring(${bounds[0]}, ${bounds[1]}): "${str.substring(...bounds)}"
    `;
    }
    
    document.getElementById("input").onkeyup = e => {
      analyzeStringWithCursor(
        e.target.value,
        getWordBoundsAtPosition(e.target.value, e.target.selectionStart),
        e.target.selectionStart
      );
    };
    <p>Type some words below. The cursor (moved by typing or arrow keys) 
    indicates the current position.</p>
    <input id="input" type="search" placeholder="Start typing some words..." />
    <pre id="analysis"></pre>

    0 讨论(0)
  • 2020-12-10 07:09
    var str = "this is a sentence";
    
    function GetWordByPos(str, pos) {
        var left = str.substr(0, pos);
        var right = str.substr(pos);
    
        left = left.replace(/^.+ /g, "");
        right = right.replace(/ .+$/g, "");
    
        return left + right;
    }
    
    alert(GetWordByPos(str, 6));
    

    P.S. Not tested throughly and no error handling yet.

    0 讨论(0)
  • 2020-12-10 07:14

    I ended up with my own solution.

    Note 1: the regular expressions are not tested thoroughly.

    Note 2: this solution is fast (even for big strings) and works even if position (pos argument) is in the middle of a word.

    function getWordByPosition(str, pos) {
      let leftSideString = str.substr(0, pos);
      let rightSideString = str.substr(pos);
    
      let leftMatch = leftSideString.match(/[^.,\s]*$/);
      let rightMatch = rightSideString.match(/^[^.,\s]*/);
    
      let resultStr = '';
    
      if (leftMatch) {
          resultStr += leftMatch[0];
      }
    
      if (rightMatch) {
          resultStr += rightMatch[0];
      }
    
      return {
          index: leftMatch.index,
          word: resultStr
      };
    }
    
    0 讨论(0)
提交回复
热议问题