提取匹配的文本及其相邻上下文n个字上游n个字下游(从左边第n次出现,从右边第n次出现)

时间:2015-06-19 07:29:33

标签: javascript css regex

我需要一个非常适合自动完成下拉菜单的文字。这需要比最初出现的策略更多的策略。使用隐藏文本或淡出选项并不能很好地工作,因为匹配的文本字符串通常位于其上下文的可见帧之外。省略号方法目前比我需要的重一点。 "显示更多"效果很好,但不是在下拉框的上下文中;除了选项之外,我不希望用户担心任何事情。我只想要一个或两个以匹配令牌为中心的上下文。有一些相关的答案,但没有任何东西可以解决右边的n和左边的n的需要。

var haystack = "r4 r3 r2 r1 needle r1 r2 r3";
var needle = "needle";
var delim = " ";
var numWords = 5;
var trimmedText = trimToNeighboringText(haystack, needle, numWords, delim);

console.log("With " + numWords + " neighboring words: \"" + trimmedText + "\"");

2 个答案:

答案 0 :(得分:1)

正则表达式可以简化这一点! 这是我的解决方案:

var haystack = "L5 L4 L3 L2 L1 needle R1 R2 R3 R4 R5 R6",
    needle = "needle",
    numWords = 3;

var result = haystack.match("(?:\\s?(?:[\\w]+)\\s?){"+numWords+"}"+needle+"(?:\\s?(?:[\\w]+)\\s?){"+numWords+"}");

console.log("With " + numWords + " neighboring words: \"" + result[0] + "\"");
  

有3个相邻字:“L3 L2 L1针R1 R2 R3”

答案 1 :(得分:0)

var haystack = "L5 L4 L3 L2 L1 needle R1 R2 R3 R4 R5 R6";
var needle = "needle";
var delim = " ";
var numWords = 3;
var trimmedText = trimToNeighboringText(haystack, needle, numWords, delim);

console.log("With " + numWords + " neighboring words: \"" + trimmedText + "\"");

function trimToNeighboringText(haystack, needle, numWords, delim) {

    // number of delimiter occurrences to look for,
    // this assumes the same on both sides
    var numDelims = numWords + 1;

    // this splits on the text that is matched
    var tokens = haystack.split(needle);

    if (tokens.length > 1) {

        var leftEllipsis = "";
        var rightEllipsis = "";

        // Get the index of the start character within the left neighbor,
        // working backwards
        var startIndex = nthOccurrenceBackwards(tokens[0], delim, numDelims);
        //console.log(startIndex + ": " + tokens[0].substr(startIndex));

        // if text is truncated at left
        if (startIndex > 0) {
            leftEllipsis = "... ";
        }
        // if text is not truncated at left
        else startIndex = 0;

        // Get the index of the end character within the right neighbor
        // working forwards (note that start is local to right neighbor)
        var endIndex = nthOccurrenceForwards(tokens[1], delim, numDelims);

        // if text is truncated at right
        if (endIndex > 0) {
            rightEllipsis = " ...";
        }
        // if text is not truncated at right
        else {
            endIndex = tokens[1].length;
        }

        // Concatenate the left fragment, the needle, and the right fragment
        return (leftEllipsis + tokens[0].substr(startIndex) + needle
                             + tokens[1].substr(0, endIndex) + rightEllipsis);

    } else {
        console.warn("Match not found");
        return haystack;
    }
}

function nthOccurrenceForwards(str, pat, n) {
    if (str.length == 0) return 0;
    //console.log("\""+str+"\"");
    var i = -1;
    while (n-- && i++ < str.length) {
        i = str.indexOf(pat, i);
        if (i==-1) break;
        //console.log("n and i "+n + "," + i)
    }
    return i;
}

function nthOccurrenceBackwards(str, pat, n) {
    if (str.length == 0) return 0;
    var j = str.length;
    while (n-- && j-- > 1) {
        j = str.lastIndexOf(pat, j);
    }
    return j;
}