Сравнить текст внутри двух элементов div с помощью javascript или jquery
У меня есть 2 тега div
<div class="one">
+
+++
+
</div>
второй тег div
<div class="two">
+ + ++++ + ++ + + +
+ ++ +++ + +++ ++ + +++
+ ++ + + ++ + + + + ++
</div>
Теперь, что я хочу найти, если .one
существует в .two
. Возможно ли, если да, как мы можем это сделать в javascript?
Обновление
Я хочу проверить шаблон +
. Я имею в виду
+
+++
+
существуют в .two
? Шаблон должен находиться в том же порядке в .two
.
@shub ответ, похоже, не работает. Вот JSFiddle ответа.
Ответы
Ответ 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'); //
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>