【问题标题】:compare text inside 2 div elements using javascript or jquery使用 javascript 或 jquery 比较 2 个 div 元素内的文本
【发布时间】:2017-05-07 10:21:05
【问题描述】:

我有以下 2 个 div 标签

<div class="one">
    +
   +++
    +
</div>

第二个 div 标签

<div class="two">
    + +   ++++  + ++  + + +
    + ++ +++ + +++ ++ + +++
    + ++ + + ++ + + + + ++ 
</div>

现在我想查找.one 是否存在于.two 中。如果可以的话,我们如何在javascript中做到这一点?

更新

我想检查+ 模式。我的意思是

+ +++ +

存在于.two?模式在.two 中的顺序必须相同。

@shub 答案似乎不起作用。这是该答案的JSFiddle

【问题讨论】:

  • 您想查看.one 中的文本是否存在于.two 中吗?或者如果一个 div 在另一个 div 内?
  • 您想匹配+ 模式吗?
  • 是的,这是可能的。我早点给你举个例子
  • 您是否正在尝试将原始代码中的模式与换行符或渲染代码中的模式相匹配——即:+ +++ + 内部:+ + ++++ + ++ + + + + ++ +++ + +++ ++ + +++ + ++ + + ++ + + + + ++
  • 我想检查 + 模式。

标签: javascript jquery html


【解决方案1】:

第 1 部分:

要查看数据如何匹配,您可能需要尝试将其转换为字母,而不是加号。

<div class="one">
    g
   tuv
    J
</div>

<div class="two">
    a b   cdef  g hi  j k l
    m no pqr s tuv wx y zAB
    C DE F G HI J K L M NO 
</div>

你必须这样做:

因为:one.innerText = g \n tuv \n J

需要将其转换为正则表达式,例如:/g|tuv|J/g

要查看交叉匹配,请将第二类的内容复制并粘贴到此站点并删除“a”、“m”和“C”之前的间距:http://regexr.com/3eumc

第 2 部分

问题是如果 "tuv" 在字符串 2 中移动,它不会被 "g" 在 "u" 上 "J" 上锁定。

要解决“g”高于“u”高于“J”的问题,我们必须将其视为游戏板的二维数据集。这意味着将字符串转换为矩阵(数组数组),其中每个字母加上每个空格都被放入数组槽中。像这样:

var matrix = [
  // 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 = columns. Remember to add +10, +20!
    [a| |b| | | |c|d|e|f| | |g| |h|i| | |j| |k| |l], // row 0
    [m| |n|o| |p|q|r| |s| |t|u|v| |w|x| |y| |z|A|B], // row 1
    [C| |D|E| |F| |G| |H|I| |J| |K| |L| |M| |N|O]    // row 2
];

现在您可以检查是否:

if ((matrix[0][13] === 'g') 
    && (matrix[1][12] === 't') && (matrix[1][13] === 'u') && (matrix[1][14] === 'v') 
    && (matrix[2][13] === 'J')) {
    /* SUCCESS when all 5 letters appear & "g" is above "u" & "u" is above "J".
    The entire cross can move left or right, but lines 1, 2 & 3 can't shift 
    independently of the other 3 lines. Otherwise it should fail.
    */
} else {
    // FAIL
}

第 3 部分...

我已经解决了这个矩阵搜索难题。请参阅我的 jsFiddle https://jsfiddle.net/briankueck/pern32vv/

这是代码外观的核心。打开那个 jsFiddle 链接上的调试开关,看看它是如何运行的。 :)

function getMatrix(cssSelector, canTrim) {
    // Built by, Clomp! @briankueck http://www.clomp.com
    var obj = $(cssSelector);
    if (obj) {
        var matrix = obj.text()

        /* Makes sure that we are selecting 3 lines, not 5 
         * as the example has a \n after <div ...>\n and before \n</div>
         */
        if (canTrim) {
            matrix = matrix.trim();
        }

        // Now split those 3 lines.
        matrix = matrix.split(/\n/);

        /* Trims each array in the matrix. Note: matrix[row] is a string, 
         * but we can treat a string as an array of characters.
         */
        if (canTrim) {
            // Trims each row, if desired.
            for (var row = 0; row < matrix.length; row++) {
                matrix[row] = matrix[row].trim();
            }
        } else {
            // Gets rid of spaces before matrix 1 in this demo.
            var maxLength = 0;
            var space = ' '; // You can also use a period here to see how it works.
            var tempMatrix = [];
            for (var row = 0; row < matrix.length; row++) {
                // This cuts the rows down (vertically) from 5 to 3.
                if (matrix[row].trim().length > 0) {
                    matrix[row] = matrix[row].replace(/\s/g, space);
                    matrix[row] = matrix[row].replace(/\t/g, space);
                    tempMatrix.push(matrix[row]);

                    if (matrix[row].length > maxLength) {
                        maxLength = matrix[row].length;
                    }
                }
            }

            /* This loops those 3 rows (horizontally) & slices the 1st character off 
             * each array if they are all identical & only contain spaces, which we are 
             * tracking with the period character '.' as dots.
             */
            var charactersToStrip = 0;
            for (var column = 0; column <= maxLength; column++) {
                for (var row = 0; row < tempMatrix.length; row++) {
                    if (tempMatrix[row][column] !== space) {
                        break;
                    } else if (row === (tempMatrix.length - 1)) {
                        charactersToStrip++;
                    }
                }
            }

            /* Strips characters, without removing the space before "g" 
             * and the space before "J".
             */
            for (var column = 0; column < charactersToStrip; column++) {
                for (var row = 0; row < tempMatrix.length; row++) {
                    tempMatrix[row] = tempMatrix[row].substring(1);
                }
            }
            matrix = tempMatrix;
        }
    }

    return matrix;
}

function matrixSearch(matrixOne, matrixTwo) {
    // Built by, Clomp! @briankueck http://www.clomp.com
    var space = ' '; // You can also use a period here to see how it works.

    // This is for " g". First we trim it, as we only want the "g" character.
    var searchChar = matrixOne[0].trim();

    // Next we find the lock position.
    var firstCharPosition = matrixTwo[0].indexOf(searchChar);

    var matchingRows = -1;
    if (firstCharPosition > -1) {

        // This should be 1 & not 0.
        var matchingCharInMatrixOne = matrixOne[0].indexOf(searchChar);

        // Now we can find the starting index of character 0 in each row of matrixTwo:
        var startIndex = firstCharPosition - matchingCharInMatrixOne;

        // This simultaneously scans rows 1, 2 & 3 in both matricies.
        var matchingRows = 0;
        for (var row = 0; row < matrixOne.length; row++) {
            /* We now know both the startIndex = 11 & the lock position = 12. 
             * So let's use them for "tuv" and " J".
             */
            var endIndex = startIndex + matrixOne[row].length;
            var i = -1;
            for (var column = startIndex; column < endIndex; column++) {
                i++;
                if (matrixOne[row][i] !== space) {
                    var matrixOneCharacter = matrixOne[row][i];
                    var matrixTwoCharacter = matrixTwo[row][column];
                    if (matrixOneCharacter !== matrixTwoCharacter) {
                        break;
                    } else if (column === (endIndex - 1)) {
                        // Found it!
                        matchingRows++;
                    }
                }
            }
        }
    }

    // Now we can find it:
    var isFoundInMatrixTwo = ((matchingRows > -1) 
        && (matchingRows === matrixTwo.length)) ? true : false;

    return isFoundInMatrixTwo;
}

var cssSelector1 = '.one';
var cssSelector2 = '.two';

var matrixOne = getMatrix(cssSelector1, false);
var matrixTwo = getMatrix(cssSelector2, true);

var isFound = matrixSearch(matrixOne, matrixTwo);
console.log('Is matrix 1 in matrix 2? ', isFound);

享受吧!

顺便说一句,来自 Clomp 的 Merry Christmas Stack Overflow 社区!

【讨论】:

    【解决方案2】:

    好吧,我们在这里已经有了很好的答案,但是……这里还有一种方法。 :)

    基本上:过滤输入,获得干净的模式/矩阵(假设一开始会有两个空格 - 必须解决这个问题!),针对另一个模式测试它(实际上 - 从两者中制作 HTML 结构和数组 =>比较它们)

    那里也有正在发生的事情的可视化表示。

    代码是暴行,可以并且应该清理(但它有点工作,哈哈):

    spacer='-';
    
    pattern=$('.one').text().replace(/ /g,spacer).split('\n');
    
    patt=pattern.filter(function(val){
       if(val.indexOf('+')>=1) {
       
       
     return val;
       }
    });
    patt = patt.map(function(x){
       return x.slice(2);
    });
    
    
    var lgth = 0;
    var longest;
    
    for(var i=0; i < patt.length; i++){ // http://stackoverflow.com/questions/6521245/finding-longest-string-in-array 
        if(patt[i].length > lgth){
            var lgth = patt[i].length;
            longest = patt[i];
        }      
    } 
    
     
    //console.log(longest.length);
    longest_sequence=longest.trim().length;
    
    matrix=[];
    
    for(j=0;j<patt.length;j++) {
    //
    if(patt[j]!=longest) {
    
    
    cleaned=patt[j]+spacer.repeat(longest.length-patt[j].length);
    cleaned=cleaned.substr(-longest_sequence);
    }
    else {
    cleaned=longest.trim();
    }
    matrix.push(cleaned);
    }
    //console.log(matrix.join('\n'));
    
    
    cells=[];
    for(i=0;i<matrix.length;i++)  {
    
    
    cells.push(matrix[i].split(''));
    $('table.small').append('<tr>');
    }
    
    $( "table.small tr" ).each(function( index ) {
    for(j=0;j<cells[index].length;j++) {
    $(this).append('<td>'+cells[index][j]+'</td>');
     }
    });
    
    
    
    data=$('.two').text().replace(/ /g,spacer).split('\n');
    data=data.filter(function(val){
       if(val.indexOf('+')>=1) {
       return val;
       }
    });
    
    data = data.map(function(x){
       return x.slice(2);
    });
    
    //console.log(data);
    //console.log(data.join('\n'));
    
    cells=[];
    for(i=0;i<data.length;i++)  {
    
    
    cells.push(data[i].split(''));
    $('table.big').append('<tr>');
    }
    
    $( "table.big tr" ).each(function( index ) {
    for(j=0;j<cells[index].length;j++) {
    $(this).append('<td>'+cells[index][j]+'</td>');
     }
    });
    
    //comparing!!!
    pattern_arr=[];
    $("table.small tr").each(function() {
    pattern_arr.push($(this).children().text().trim())
    });
    function arraysEqual(a1,a2) {
        /* WARNING: arrays must not contain {objects} or behavior may be undefined */
       // console.log(JSON.stringify(a1)+':'+JSON.stringify(a2));
       // console.log('________________________________________');
        return JSON.stringify(a1)==JSON.stringify(a2);
    }
    
    count=-1;
    timer=setInterval(function(){ 
    count++;
    sliced_arr=[];
    slices=[];
    $( "table.big tr" ).each(function( index ) { 
    $(this).children('td').removeClass('search');
    sliced=$(this).children('td').slice( count,count+longest_sequence );
    slices.push(sliced);
    $(sliced).addClass('search');
    
    
    
    sliced_arr.push($(sliced).text().trim());
    
    
    
    
    if(arraysEqual(pattern_arr,sliced_arr)) {
    
    
    
    //$(sliced).addClass('found').removeClass('search');
    
    $.each( slices, function( key, value ) {
    $(this).addClass('found').removeClass('search');
    });
    //$(slices).addClass('found').removeClass('search');
    
    $('#status').text('Found!');
    
    
    
    
    
    clearInterval(timer);
     }
     
    for(i=0;i<sliced_arr.length;i++)
     if(sliced_arr[i]=="") {
    
      clearInterval(timer);
    
    $('#status').text('Not found!');
     break;
    
     }
    
    
    
    });
    }, 1000);
    .one, .two {
      font-size:22px;
    }
    
    table.big {
      border:1px solid #666;
    padding:0;
      border-collapse:collapse;
    }
    table.big td {
      border:1px solid #666;
     
      padding:5px;
      margin:0;
    }
    
    table.small {
      border:1px solid red;
    padding:0;
      border-collapse:collapse;
    }
    table.small td {
      border:1px solid red;
     
      padding:5px;
      margin:0;
    }
    
    .found {
      font-weight:bold;
      color:white;
      background:green;
    }
    .search {
      font-weight:bold;
      color:white;
      background:orange;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="one"><pre>
       +
      +++
       +
     </pre></div>
    <table class="small">
    
    </table>
    <div class="two"><pre>
      + +   ++++  + ++  + + +
      + ++ +++ + +++ ++ + +++
      + ++ + + ++ + + + + ++ 
    </pre></div>
    
    <table class="big">
    
    </table>
    <div id="status">
    </div>

    【讨论】:

      【解决方案3】:

      @2619 的previous post 表现出对Bliffoscope 问题的兴趣。假设div.onediv.two的文字内容,定宽字体,ascii艺术风格,是由+拼凑而成的图片,表示活动像素,而“ "(空格)<strong>无效</strong>。这个想法是找到我们可以将div.one 放在div.two 上的哪个位置,以便这两个模式形成更多的交叉点。我只考虑两个给定图像的 active 像素坐标的交集。

      在此示例中,+ 被替换为 o 以突出显示每个匹配项的交叉点。使用canvas 的简化版本可以找到here

      在下面的SO sn-pJSFiddle demo 中,单击NextPrevious 链接,或按键盘上的箭头按钮来浏览匹配项。

      _main.best_positions() 返回每​​个可能叠加的交叉点数,具有任意程度的误差容忍度,按交叉点数排序(更多匹配优先)。

      var PatternFinder;
      
      PatternFinder = (function(win, doc, undefined) {
        'use strict';
      
        var _main = {
      
          selectors: {
            object_1_pattern: ".one",
            background_pattern: ".two",
            results: ".three",
            next_button: ".next",
            previous_button: ".previous",
            match_score: ".intersecting_coords",
            match_nr: ".match_nr",
          },
          cache: {
            object_text_string: '',
            context_text_string: ''
          },
          init: function() {
      
            _main.cache.object_text_string = $(_main.selectors.object_1_pattern).text();
            _main.cache.context_text_string = $(_main.selectors.background_pattern).text();
      
            // Parse our images from the text strings.
            _main.serialized_context = _main.serialize_map(_main.cache.context_text_string);
            _main.serialized_object = _main.serialize_map(_main.cache.object_text_string);
      
            // Find the position of the object with larger amount of intersecting coordinates
            _main.best_positions = _main.get_best_position(_main.serialized_context, _main.serialized_object);
            _main.current_result = _main.best_positions.length - 1;
      
            // Draw initial results
            _main.print_output(_main.current_result);
      
            // Handle user input
            $(_main.selectors.next_button).click(function() {
              _main.current_result -= 1;
              _main.print_output();
            });
            $(_main.selectors.previous_button).click(function() {
              _main.current_result += 1;
              _main.print_output();
            });
            // Keyboard: Arrow keys
            $(document).keydown(function(e) {
              switch (e.which) {
                case 37:
                  { // left
                    _main.current_result += 1;
                    _main.print_output();
                    break;
                  }
                case 39:
                  { // right
                    _main.current_result -= 1;
                    _main.print_output();
                    break;
                  }
                default:
                  return;
              }
              e.preventDefault(); // prevent the default action (scroll / move caret)
            });
          },
      
          // Highlight an intersection.
          // Replace "+" by "o" in coords _x, _y.
          highlight_match: function(_x, _y, background) {
            var x = 0,
              y = 0,
              i = 0,
              output = "",
              c;
            for (i = 0; i < background.length; i += 1) {
              c = background[i];
              if (c == "+" && x == _x && y == _y) {
                output = output + "o";
              } else {
                output = output + c;
              }
              x += 1;
              if (c == "\n") {
                x = 0;
                y += 1;
              }
            }
      
            return output;
          },
      
          // Receive the translated serialized object,
          // and the original text string for the background.
          // Return the background text string, with the matches 
          // between it and serialized_object highlighted.
          merge_and_deserialize: function(serialized_object, background) {
            var i;
            for (i = serialized_object.length - 1; i >= 0; i--) {
              background = _main.highlight_match(serialized_object[i][0], serialized_object[i][1], background);
            }
            return background;
          },
      
          // Receive a text string like the one from the Stack Overflow ticket, 
          // return an array of coordinates of filled in pixels (+ or space).
          serialize_map: function(char_map) {
            var x = 0,
              y = 0,
              c,
              i,
              map = [];
            for (i = 0; i < char_map.length; i += 1) {
              c = char_map[i];
              if (c == "+") {
                map.push([x, y]);
              }
              x += 1;
              if (c == "\n") {
                x = 0;
                y += 1;
              }
            }
            return map;
          },
      
          // Find number of intersections between two images (that's where the magic happens).
          // Found here: https://gist.github.com/lovasoa/3361645
          array_intersect: function() {
            var a, d, b, e, h = [],
              l = [],
              f = {},
              g;
            g = arguments.length - 1;
            b = arguments[0].length;
            for (a = d = 0; a <= g; a += 1) {
              e = arguments[a].length, e < b && (d = a, b = e);
            }
            for (a = 0; a <= g; a += 1) {
              e = a === d ? 0 : a || d;
              b = arguments[e].length;
              for (l = 0; l < b; l += 1) {
                var k = arguments[e][l];
                f[k] === a - 1 ? a === g ? (h.push(k), f[k] = 0) : f[k] = a : 0 === a && (f[k] = 0);
              }
            }
            return h;
          },
      
          // Translate the coordinates of a serialized image.
          translate: function(coords, ix, iy) {
            return [coords[0] + ix, coords[1] + iy];
          },
      
          // Find in which position the object has more intersections with the background.
          get_best_position: function(context, object) {
      
            // Calculate image dimensions
            var context_width = context.sort(function(a, b) {
                return b[0] - a[0];
              })[0][0],
              context_height = context.sort(function(a, b) {
                return b[1] - a[1];
              })[0][1],
              object_width = object.sort(function(a, b) {
                return b[0] - a[0];
              })[0][0],
              object_height = object.sort(function(a, b) {
                return b[1] - a[1];
              })[0][1];
            // Swipe context, store amount of matches for each patch position.
            var similaritudes = [],
              cx, cy, intersection, translated_object;
      
            for (cx = -object_width; cx < context_width; cx += 1) {
              for (cy = -object_height; cy < context_height; cy += 1) {
                translated_object = object.map(function(coords) {
                  return _main.translate(coords, cx, cy);
                });
      
                intersection = _main.array_intersect(context, translated_object);
      
                if (intersection.length > 0) {
                  similaritudes.push({
                    coords: [cx, cy],
                    similaritudes: intersection.length
                  });
                }
      
              }
            }
            // Return coords,
            // sorted by those for which number of matches was greater.
            return similaritudes.sort(function(a, b) {
              return a.similaritudes - b.similaritudes;
            });
          },
      
          print_output: function() {
      
            var positioned_object;
      
            // Get the coordinates of one of our matches.
            _main.current_result = Math.max(_main.current_result, 1);
            _main.current_result = Math.min(_main.current_result, _main.best_positions.length - 1);
      
            var score = _main.best_positions.slice(_main.current_result)[0].similaritudes;
            var best_position = _main.best_positions.slice(_main.current_result)[0].coords;
      
            // Translate our image patch to the position defined by _main.current_result.
            positioned_object = _main.serialized_object.map(function(coords) {
              return _main.translate(coords, best_position[0], best_position[1]);
            });
      
            // Produce merged images (background after replace).
            var final_image = _main.merge_and_deserialize(positioned_object, _main.cache.context_text_string);
            // Print image and information
            $(_main.selectors.results).text(final_image);
            $(_main.selectors.match_score).text(score);
            $(_main.selectors.match_nr).text(_main.best_positions.length - _main.current_result);
          }
      
        };
      
        // Expose methods
        _main.public_methods = {
          init: _main.init,
        };
        return _main.public_methods;
      
      }(window, document));
      
      PatternFinder.init();
      .one,
      .two {
        display: none;
      }
      .three {
        white-space: pre;
        font-family: "Lucida Console", Monaco, "Courier New", Courier, monospace;
        margin: 0 0 20px 0;
      }
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <div class="one">
          +
         +++
          +
      </div>
      <div class="two">
          + +   ++++  + ++  + + +
          + ++ +++ + +++ ++ + +++
          + ++ + + ++ + + + + ++ 
      </div>
      <h3>Match: <span class="match_nr"></span></h3> 
      <h5>Intersecting coordinates: <span class="intersecting_coords"></span></h5>
      <div class="three"></div>
      <nav>
      <a class="previous" href="#">Previous</a>
      <a class="next" href="#">Next</a>
      </nav>
      <p><sub>Click Next and Previous or use the keyboard arrows to see other possible matches.</sub></p>

      【讨论】:

        【解决方案4】:

        下面的代码 sn-p 查找“二”div 中所有出现的“一”模式,如标记中所写。结果在控制台输出中报告(行索引和行中位置)。

        学分:

        1. Clomp 的 cmets 帮助我理解问题是关于标记模式的
        2. 我从this answer借了getIndicesOfTim Down

        function find() {
            var i, j, k;
            var txtOne = $('.one').text();
            var txtTwo = $('.two').text();
            var linesOne = txtOne.split("\n");
          
            // Get search patterns from "one"
            var patterns = getSearchPatterns(linesOne);
        
            // Get content lines from "two"
            var linesTwo = txtTwo.split("\n");
            while (linesTwo.length > 0 && !linesTwo[0]) {
                linesTwo.shift();
            }
        
            // Get all the positions of all patterns in all lines
            var searchResults = [];
            var patternInLines, positionsInLine;
            for (i = 0; i < patterns.length; i++) {
                patternInLines = [];
                for (j = 0; j < linesTwo.length; j++) {
                    positionsInLine = getIndicesOf(patterns[i], linesTwo[j], true);
                    patternInLines.push(positionsInLine);
                }
                searchResults.push(patternInLines);
            }
        
            // Get the occurrences of all patterns at the same position on consecutive lines
            var results = [];
            var firstPatternInLine, firstPatternPosition, patternInLine, found;
            var firstPattern = searchResults[0];
            for (j = 0; j < linesTwo.length - patterns.length; j++) {
                firstPatternInLine = firstPattern[j];
                for (k = 0; k < firstPatternInLine.length; k++) {
                    firstPatternPosition = firstPatternInLine[k];
                    found = true;
                    for (i = 1; i < patterns.length; i++) {
                        patternInLine = searchResults[i][j + i];
                        if (patternInLine.indexOf(firstPatternPosition) < 0) {
                            found = false;
                            break;
                        }
                    }
                    if (found) {
                        results.push({
                            line: j,
                            position: firstPatternPosition
                        })
                    }
                }
            }
        
            // Display results
            for (i = 0; i < results.length; i++) {
                console.log(results[i]);
            }
            if (results.length < 1) {
                console.log("No occurrence found");
            }
        }
        
        // Trim the search lines to get the minimal search "block"
        function getSearchPatterns(lines) {
            var items = [];
            var result = [];
            var i, txt, offset, item;
            var minOffset = 1000000;
            var maxLength = 0;
            for (i = 0; i < lines.length; i++) {
                txt = lines[i].trim();
                if (txt) {
                    offset = lines[i].indexOf(txt);
                    items.push({
                        str: txt,
                        offset: offset
                    });
                    minOffset = Math.min(offset, minOffset);
                }
            }
            for (i = 0; i < items.length; i++) {
                item = items[i];
                item.offset -= minOffset;
                maxLength = Math.max(item.offset + item.str.length, maxLength);
            }
            for (i = 0; i < items.length; i++) {
                item = items[i];
                result.push(paddRight(paddLeft(item.str, item.offset), maxLength));
            }
            return result;
        }
        
        function paddLeft(str, count) {
            var padding = "";
            for (var i = 0; i < count; i++) {
                padding += " ";
            }
            return padding + str;
        }
        
        function paddRight(str, length) {
            var result = str;
            while (result.length < length) {
                result += " ";
            }
            return result;
        }
        
        // Find all positions of search string in string
        // By Tim Down at https://stackoverflow.com/a/3410557/1009922
        function getIndicesOf(searchStr, str, caseSensitive) {
            var searchStrLen = searchStr.length;
            if (searchStrLen == 0) {
                return [];
            }
            var startIndex = 0, index, indices = [];
            if (!caseSensitive) {
                str = str.toLowerCase();
                searchStr = searchStr.toLowerCase();
            }
            while ((index = str.indexOf(searchStr, startIndex)) >= 0) {
                indices.push(index);
                startIndex = index + searchStrLen;
            }
            return indices;
        }
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <div class="one">
             a
            bcd
             e
        </div>
        <div class="two">
            ++ + ++ ++++ + ++ + + + a 
            + +   ++++  a ++  + + +bcd
            + a  +++ + bcd ++ + +++ e 
            +bcd + + ++ e + + + ++ ++
            + e ++++++++++++++++++++++
        </div>
        <button onclick="find()">Test!</button>

        【讨论】:

        • 乍一看,这个代码示例似乎可以工作......因为所有数据都使用“+”加号。如果将数据转换为字母,则此代码示例将与 OP 要求的垂直和水平模式不匹配。它试图选择中间“+++”两侧的水平加号,而不是上面或下面的+。
        • @Clomp - 我明白你的意思。如果你是对的,OP 想要匹配标记中给出的模式,而不是呈现的 HTML(它回答了 cmets 中 Haltersweb 提出的问题)。
        • 如果数据将包含相同的数据元素,其中每个 + 出现在,那么您的代码将起作用,但这是有风险的,因为我们不知道数据是否相同或不同。 OP确实提到:“模式必须在.two中以相同的顺序排列”。所以我写了一个答案,可以针对不同的数据做到这一点。无论哪种方式,我们都试图帮助他。 :)
        【解决方案5】:

        您的 jquery 代码将如下所示。你可以用这个逻辑玩更多

            jQuery().ready(function(){
        var lines = $(".two").text().split("\n");
        for(i=1;i<=lines[1].length;i++){
            if(lines[1][i]=='+' 
          && lines[2][i-1]!='undefined' && lines[1][i]==lines[2][i-1] 
          && lines[2][i]!='undefined' && lines[1][i]==lines[2][i] 
          && lines[2][i+1]!='undefined' && lines[1][i]==lines[2][i+1]
          && lines[3][i]!='undefined' && lines[1][i]==lines[3][i] 
          ){
          console.log('exists');
          }
        }
        });
        

        这里是小提琴:https://jsfiddle.net/ahmadasjad/12eqhs7L/5/

        【讨论】:

        • 你能看看这个jsfiddle.net/12eqhs7L/4。当我更改 .one 模式时,它仍然可以正常工作。
        • 我的小提琴只是为了那个小人物,你可以基于这个构建一个逻辑。
        • 而且你看的东西也是可以的,先让你试试,不能让我知道。
        • 好吧,在.two 中,文本没有以我在问题中显示的相同模式(在小提琴中)显示。可能是这个原因?
        • 早点再次检查,有一些错误。 .two 中有一种可用的模式,您在匹配时也可以用肉眼看到。
        【解决方案6】:

        在之前的帖子中有一些非常有趣的想法,我喜欢添加更紧凑的函数式方法(它使用 lodash)。主要思想是修剪匹配文本并将其与目标文本上的移动窗口(cut)进行比较。在该函数之上还返回从左侧找到匹配的位置。 See working Fiddle:

        function findText(text, search) {
          const width = maxWidth(search)-minTrim(search);
          const matcher = cut(search, minTrim(search),width).join('');
          return _.range(text[1].length) // create array of possible matches
                    .map(col=>cut(text, col, width).join(''))
                    .indexOf(matcher)+1; // and match with matcher
        }
        
        // Returns left padding size, e.g. 3 in the example
        function minTrim(t) {
          return _.min(t.filter(s=>!!s).map(s=>s.length-_.trimStart(s).length))
        }
        
        // Returns window within $text at $start position with $width
        function cut(text, start, width) {
          return text.map(s=>_.padEnd(s.substr(start,width),width))
        }
        
        // Returns maximum width of the line within text
        function maxWidth(text) {
          return _.max(text.map(s=>s.length))
        }
        

        函数findText可以这样使用:

        const two=document.getElementsByClassName("two")[0].innerHTML.split('\n');
        const one=document.getElementsByClassName("one")[0].innerHTML.split('\n');
        alert((pos=findText(two,one)) ? `found at position ${pos}` : "not found");
        

        选项 2 如果字符串仅包含 '+' 且长度不超过 64 个字符,我们可以将上述函数转换为位掩码匹配。例如。将每个字符串转换为二进制数字,然后移动目标字符串,应用搜索掩码(例如上面示例中的窗口)并比较数字。 See working fiddle:

        function findTextBin(text,search) {
          const toBin=str=>str.split('')
                  .reduce((res,c)=>res<<1|(c==='+'?1:0),0)
          let one=search.map(toBin)
          let mask=toBin(_.max(one).toString(2).split('').map(c=>'+').join(''))
          let two=text.map(toBin)
          let length=_.max(text.map(str=>str.length))
          for(let i=length; i; i--,two=two.map(num=>num>>1))
            if(two.every((num,row)=>(num&mask)===one[row]))
              return i-mask.toString(2).length;
          return false;
        }
        

        【讨论】:

          【解决方案7】:

          只是一个建议,但您可以对内容进行哈希处理以进行比较。此代码使用 CryptoJS 库生成 MD5 哈希

          <script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/md5.js"></script>
          <script>
              var div1 = CryptoJS.MD5( $('.one').text() );
              var div2 = CryptoJS.MD5( $('.two').text() );
              if(div1 === div2) {
                  // your code here
             }
          </script>
          

          【讨论】:

            【解决方案8】:

            假设两者中的行数相同,以下解决方案使查找模式变得简单。

            前提条件:

            此方案需要pattern,目标形成如下:

            var pattern = [
              ' + ',
              '+++',
              ' + '
            ];
            
            var target = [
              '+ +   ++++  + ++  + + +',
              '+ ++ +++ + +++ ++ + +++',
              '+ ++ + + ++ + + + + ++ '
            ];
            

            我认为一个简单的 javascript 操作可以做到这一点——逐行读取 HTML,并将其附加到数组中。如果需要,我也可以提供该代码。

            工作原理:

            代码首先决定pattern的宽度,然后继续在target数组中逐列查找这种宽度的模式。当检测到宽度较小的模式或找到匹配项时,循环停止。

            代码:

            // Our core function
            function matches(target, pattern) {
            
              if (pattern.length > target.length) {
                return false;
              }
            
              var patternWidth = findPatternWidth(pattern);
              var startIndex = 0;
              var currentPattern = getNextPattern(target, startIndex, patternWidth);
            
              while (patternValid(currentPattern, patternWidth)) {
                if (identicalArrays(currentPattern, pattern)) {
                  return true;
                }
            
                startIndex++;
                currentPattern = getNextPattern(target, startIndex, patternWidth);
              }
            
              return false;
            }
            
            // -*-*-*-*-*- HELPER FUNCTIONS -*-*-*-*-*-*
            
            // Finds the width of the pattern we want to match
            function findPatternWidth(pattern) {
              var maxWidth = 0;
            
              for (var i = 0; i < pattern.length; i++) {
                if (pattern[i].length > maxWidth) {
                  maxWidth = pattern[i].length;
                }
              }
            
              return maxWidth;
            }
            
            // Finds the next suitable pattern, starting with an index, of a maximum width
            function getNextPattern(target, startIndex, maxWidth) {
              var result = [];
            
              for (var i = 0; i < target.length; i++) {
                result.push(target[i].substr(startIndex, maxWidth));
              }
            
              return result;
            }
            
            // Checks if two non-nested arrays are identical
            function identicalArrays(source, target) {
              if (source.length !== target.length) {
                return false;
              }
            
              for (var i = 0; i < source.length; i++) {
                if (source[i] !== target[i]) {
                  return false;
                }
              }
            
              return true;
            }
            
            // Checks if a given pattern is of given width
            function patternValid(pattern, maxWidth) {
              for (var i = 0; i < pattern.length; i++) {
                if (pattern[i].length < maxWidth) {
                  return false;
                }
              }
            
              return true;
            }
            

            我相信可以扩展这种方法以摆脱这种假设the number of rows are same in both

            【讨论】:

              【解决方案9】:

              要在另一个字符串中查找模式,首先要找到加号相对于彼此的位置;然后检查第二个字符串中的加号是否在相同的相对位置。

              findCoordinates 函数查找模式中加号相对于模式字符串中第一个加号的位置。对于模式,

               +
              +++
               +
              

              顶行中的+ 位于 (0,0)。第二行中的第一个 + 位于 (-1,1),因为它在第一个 + 的下方和左侧一个位置。同理,其他加号分别为(0,1)、(1,1)、(0,2)。

              hasPattern 函数使用相对坐标来检查模式是否存在于第二个字符串中。对于第二个字符串中的每个+,它会检查相应位置是否还有其他+ 字符以匹配模式。对于示例模式,该函数将检查字符是否为加号。如果是+,则检查左下方、正下方、右下方和下方两行的字符。如果这些字符也是加号,则该函数返回 true。

              function findCoordinates(string) {
                var rows = string.split('\n');
                var coordinates = [];
                var first = null;
              
                for (var i = 0; i < rows.length; i++) {
                  for (var j = 0; j < rows[i].length; j++) {
                    if (rows[i][j] === '+') {
                      if (first === null) {
                        first = {x:j, y:i};
                      }
                      coordinates.push({x:j-first.x, y:i-first.y});
                    }
                  }
                }
              
                return coordinates;
              }
              
              function hasPattern(string, coordinates)
              {
                var rows = string.split('\n');
                var matches = 0;
                var coordinate = null;
              
                for (var i = 0; i < rows.length; i++) {
                  for (var j = 0; j < rows[i].length; j++) {
                    if (rows[i][j] === '+') {
                      matches = 0;
                      for (var k = 0; k < coordinates.length; k++) {
                        coordinate = coordinates[k];
                        if (rows[i + coordinate.y] && rows[i + coordinate.y][j + coordinate.x] === '+') {
                          matches++;
                        }
                      }
                      if (matches === coordinates.length) {
                        return true;
                      }
                    }
                  }
                }
                return false;
              }
              
              var one = document.querySelector('.one');
              var two = document.querySelector('.two');
              
              console.log(hasPattern(two.textContent, findCoordinates(one.textContent)));
              div {
                font-family: monospace;
                white-space: pre;
              }
              <div class="one">
                  +
                 +++
                  +
              </div>
              
              <div class="two">
                  + +   ++++  + ++  + + +
                  + ++ +++ + +++ ++ + +++
                  + ++ + + ++ + + + + ++ 
              </div>

              【讨论】:

                【解决方案10】:
                $('.one').diffString($('.two').html());
                

                【讨论】:

                • 欢迎来到 Stackoverflow! diffString 是什么?哪个库支持它?此外,您最好将代码格式化为代码。
                • @ykaragol +1 感谢您的好评
                【解决方案11】:

                如果test patternsource pattern 的行数不同,此解决方案将不起作用。

                这个想法是创建一个模式的连续列的字符串。然后我们可以使用indexOf轻松检查模式是否存在

                例如,这样的模式:

                1 2 3
                +   +
                  + 
                + + +
                

                变成"+ + +++ +"; // equivalent of ["+ +"," ++","+ +"].join("");

                这是小提琴https://jsfiddle.net/flyinggambit/vcav3c46/

                function getVerticalPattern(pattern){
                  // split the pattern in to an array, each item represents each line
                  var pattern = pattern.split("\n"); 
                  var numLines = pattern.length; // Find the number of lines
                
                  // Find the longest string
                  var longestString = 0;
                  for(var i=0; i<pattern.length; ++i){
                      longestString = pattern[i].length;
                  }
                
                  // Rearrange the pattern
                  var newPattern = [];
                  for (var i=0; i<longestString; i++){
                      for (var j=0; j<numLines; j++){
                          if(pattern[j] && pattern[j].length){ // sometimes the split was creating empty strings ""
                            newPattern.push(pattern[j][i]);
                          }
                      }   
                  }
                  return newPattern.join("");
                }
                
                function findPattern(testPattern, srcPattern){
                  return (getVerticalPattern(srcPattern)).indexOf(getVerticalPattern(testPattern));
                }
                
                var srcPattern = document.getElementsByClassName("two")[0].innerHTML;
                var testPattern = document.getElementsByClassName("one")[0].innerHTML;
                var result = findPattern(testPattern, srcPattern);
                
                if(result !== -1){
                  console.log("pattern found");
                }else{
                  console.log("pattern not found");
                }
                <pre class="one">
                    +
                   +++
                    +
                </pre>
                
                
                <pre class="two">
                    + +   ++++  + ++  + + +
                    + ++ +++ + +++ ++ + +++
                    + ++ + + ++ + + + + ++ 
                </pre>

                回答这个问题既激动又有趣:)

                【讨论】:

                • @Downvoter 请解释为什么?只是投票和离开对任何人都没有帮助
                【解决方案12】:

                这又快又丑,还有一些错误检查和优化有待完成......但足以展示这个概念:

                var pattern = [
                  '+ + ',
                  '+ ++',
                  '+ ++'
                ];
                
                var target = [
                  '+ +   ++++  + ++  + + +',
                  '+ ++ +++ + +++ ++ + +++',
                  '+ ++ + + ++ + + + + ++ '
                ];
                
                function getAllIndexes(arr, val) {
                    var indexes = [], i = -1;
                    while ((i = arr.indexOf(val, i+1)) != -1){
                        indexes.push(i);
                    }
                    return indexes;
                }
                
                function checkNextRow(pattern, target, pRow, tRow) {
                  var matchePos = target[i].indexOf(pattern[0]);
                }
                
                
                function test(pattern, target) {
                  //get pattern hights for later
                  var pH = pattern.length;
                  var tH = target.length;
                
                  //target should have equal or more rows
                  if (tH < pH) return 'not found';
                
                  //which is the lowest row of the target where top row of the pattern can be matched?
                  tLastTop = tH - pH;
                
                
                  //function to check row of pattern
                  function checkRest(pRow, tRow, hPosMatch) {
                    console.log('searching for '+pattern[pRow]+' in '+target[tRow]);
                    var matchPos = target[tRow].indexOf(pattern[pRow], hPosMatch);
                
                    console.log('search result>>>>'+matchPos);
                    if (matchPos >= 0 && matchPos === hPosMatch) {
                      if (pRow === pH-1) {
                        console.log('last row of pattern matched');
                        return true; //last row of pattern matched
                      } else {
                        console.log('calling checkRow from itself');
                        return checkRest(pRow+1, tRow+1, hPosMatch);
                      }
                    } else {
                      console.log('pattern not found in row, returning false',hPosMatch, matchPos);
                      return false;
                    }
                  }
                
                  //search for top row of pattern
                  for (i = 0; i <= tLastTop; i++) {
                    //get all accurance indexes of patern's first row
                    var matches = getAllIndexes(target[i], pattern[0]);
                    console.log("matches",matches);
                    if (matches.length <= 0) continue;
                
                    //try other rows for each accurance position
                    for (h = 0; h <= matches.length; h++) {
                      var hPosMatch = matches[h];
                      console.log('calling checkRow from iterator');
                      var result = checkRest(1,i+1,hPosMatch);
                      if (result) return true;
                    }
                  }
                  return false;
                
                
                }
                
                console.log(test(pattern, target));
                

                我跳过了将 DIV 内容加载到模式/目标变量中,因为它看起来微不足道。另外我假设空格对模式也很重要,这意味着“+ +”不匹配“+++

                JSBin 在这里:http://jsbin.com/kayeyi/edit?js,console

                【讨论】:

                  【解决方案13】:

                  为了不使事情过于复杂,我对输入做了一些假设:

                  1. 输入中的行数相等
                  2. 输入中的任何空行都可以省略
                  3. 输入的每个非空行都应在“缺失”的地方包含空白字符
                  4. 两个输入中的空白字符相同,不是换行符

                  除了从 DOM 收集数据之外,该解决方案还经过以下步骤:

                  1. 模式和输入都转换为字符串数组,每个字符串代表一行。数组必须具有相同的长度(假设 1
                  2. 为每对行收集可能匹配的列表 - 输入字符串中包含模式字符串的所有索引的列表
                  3. 结果列表被扁平化为单个列表,所有索引都被计算在内。现在对于每个可能的索引,我们都有匹配成功的行数
                  4. 过滤结果以仅保留最大计数的索引

                  还有一个working fiddle的解决方案

                  function indexOf(pattern, input){
                  	if(pattern.length !== input.length) throw 'Works only for same number of lines';
                  	var counts = [].concat(...input.map((s,i) => allMatches(pattern[i],s))).reduce((r,e) => (r[e] = (r[e] || 0) + 1, r), {}); //find all matches for all lines and flatten the result
                    var stops = Object.keys(counts).filter(k => counts[k] === pattern.length); //get only those that span across all the lines
                    return stops[0] || -1; //first found or -1 if empty
                  }
                  function allMatches(substr, str){
                  	var result = [], index = 0;
                    while(~(index = str.indexOf(substr, index))) // ~(-1) is falsy
                    	result.push(index++);
                    return result;
                  }
                  function readContent(element){
                  	return (element.value || element.textContent).split(/[\r\n]+/).filter(s => s.length); //get all non-empty lines
                  }
                  function showResult(pattern, input){
                  	var chars = Array(input[0].length).fill('\xa0'); // &nbsp;
                  	chars[indexOf(pattern, input)] = '^';
                    document.querySelector('.result').textContent = chars.join('');
                  }
                  function updater(){
                  	showResult(	readContent(document.querySelector('.one')),
                  							readContent(document.querySelector('.two'))
                  	);
                  }
                  document.querySelector('.one').addEventListener('input', updater);
                  document.querySelector('.two').addEventListener('input', updater);
                  updater();
                  .one, .two, .result{
                    padding: 0;
                    margin: 0;
                    font-family: monospace;
                    width: 100%;
                    font-size: 1rem;
                  }
                  <textarea class="one" rows="4">
                   + 
                  +++
                   + 
                  </textarea>
                  <textarea class="two" rows="4">
                  + +   ++++  + ++  + + +
                  + ++ +++ + +++ ++ + +++
                  + ++ + + ++ + + + + ++ 
                  </textarea>
                  <div class="result"></div>

                  【讨论】:

                    猜你喜欢
                    • 2022-08-16
                    • 1970-01-01
                    • 2022-01-18
                    • 1970-01-01
                    • 2021-08-06
                    • 2013-04-26
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多