Подтвердить что ты не робот

Сравнить текст внутри двух элементов div с помощью javascript или jquery

У меня есть 2 тега div

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

второй тег div

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

Теперь, что я хочу найти, если .one существует в .two. Возможно ли, если да, как мы можем это сделать в javascript?

Обновление

Я хочу проверить шаблон +. Я имею в виду

+ +++ +

существуют в .two? Шаблон должен находиться в том же порядке в .two.

@shub ответ, похоже, не работает. Вот JSFiddle ответа.

4b9b3361

Ответ 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 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);

Наслаждайтесь!

Btw, сообщество Рождества Рождества из Clomp!

Ответ 2

Ну, у нас уже есть отличные ответы здесь, но... вот еще один подход.:)

В принципе: вход фильтра, получить чистый шаблон/матрицу (предполагается, что в начале будет два пробела - нужно исправить это!), протестировать его против другого шаблона (на самом деле - создать структуру HTML и массивы из обоих = > сравните их)

Визуальное представление о том, что происходит, тоже.

Код - это беспринципность, может и следует очищаться (но это работает, lol):

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 предыдущий пост показывает интерес к проблеме Bliffoscope. Учитывая, что текстовое содержимое div.one и div.two, шрифт с фиксированной шириной, стиль стиля ascii, представляют собой изображения, собранные вместе с +, что означает активный пиксель, и "(пробел) неактивный. Идея состоит в том, чтобы найти, в какой позиции мы могли бы разместить div.one над div.two, так что эти два шаблона образуют больше пересечений. Я рассматриваю только пересечение координат активных пикселей двух заданных изображений.

В этом примере + заменяется на o, чтобы выделить пересечения каждого совпадения. Упрощенную версию, использующую canvas, можно найти здесь.

В приведенном ниже фрагменте SO и в JSFiddle demo щелкните ссылки Next и Previous или нажмите кнопки со стрелками клавиатуры, чтобы перемещаться по спичкам.

_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 Qaru 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 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

В приведенном ниже фрагменте кода найдены все вхождения "одного" шаблона в "двух" div, как написано в разметке. Результаты отображаются на выходе консоли (индекс строки и позиция в строке).

Кредиты:

  • Комментарии Clomp помогли мне понять, что вопрос о шаблоне разметки
  • Я взял getIndicesOf из этот ответ Tim 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 /questions/100212/how-to-find-indices-of-all-occurrences-of-one-string-in-another-in-javascript/637324#637324
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>

Ответ 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/

Ответ 6

В предыдущих сообщениях есть довольно интересные идеи, мне нравится добавлять функциональный подход, который более компактен (он использует lodash). Основная идея состоит в том, чтобы обрезать соответствующий текст и сравнить его со сдвижным окном (вырезанием) целевого текста. В верхней части этой функции также возвращается позиция, где совпадение находится слева. Смотрите рабочий скрипт:

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 символов, мы можем преобразовать функцию выше в соответствие с битовой маской. Например. преобразовать каждую строку в двоичную цифру, затем сменить целевую строку, применить маску поиска (например, окно в приведенном выше примере) и сравнить числа. См. рабочую скрипту:

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

$('.one').diffString($('.two').html());

Ответ 9

Предполагая, что число строк одинаково в обоих, следующее решение позволяет легко найти шаблон.

Предпосылки:

Это решение нуждается в шаблоне, а цель должна быть сформирована следующим образом:

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.

Ответ 10

Чтобы найти шаблон в другой строке, сначала найдутся позиция плюсов относительно друг друга; то плюсы во второй строке проверяются, если они находятся в одинаковых относительных положениях.

Функция 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>

Ответ 11

Это решение не будет работать, если количество строк test pattern и source 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>

Ответ 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 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 в шаблонные/целевые vars, поскольку это кажется тривиальным. Также я предполагал, что пробелы также важны для шаблона, что означает, что "+ +" не соответствует "+++"

JSBin здесь: http://jsbin.com/kayeyi/edit?js,console

Ответ 13

Чтобы не перекомплементировать вещи, я сделал некоторые предположения о входах:

  • Количество строк в входах равно
  • Любая пустая строка с входов может быть опущена
  • Каждая непустая строка входов должна содержать пробельные символы в "отсутствующих" местах.
  • Символ пробела на обоих входах один и тот же, и он не прерывает строку

Помимо сбора данных из DOM решение проходит следующие шаги:

  • Оба шаблона и ввод преобразуются в массивы строк, каждая строка для строки. Массивы должны иметь одинаковую длину (предположение 1)
  • Для каждой пары строк отображается список возможных совпадений - список всех индексов во входной строке, в которую включена строка шаблона
  • Списки результатов сглаживаются в один список и учитываются все индексы. Теперь для каждого возможного индекса у нас есть количество строк, в которых совпадение выполнено успешно.
  • Отфильтровать результат, чтобы оставить только индексы с максимальным количеством

Существует также рабочая скрипта решения

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>