comparer du texte à l’intérieur de 2 éléments div en utilisant javascript ou jquery

J’ai 2 balises div suivantes

+ +++ +

deuxième balise div

 
+ + ++++ + ++ + + + + ++ +++ + +++ ++ + +++ + ++ + + ++ + + + + ++

Maintenant ce que je veux trouver si .one existe dans .two . Est-ce possible si oui comment pouvons-nous le faire en javascript?

Mettre à jour

Je veux vérifier le motif + . Je veux dire

+ +++ +

existe-t-il dans .two ? Le modèle doit être dans le même ordre en .two .

La réponse de @shub ne semble pas fonctionner. Voici JSFiddle de cette réponse.

Partie 1:

Pour voir comment les données correspondent, vous pouvez essayer de transformer cela en lettres, au lieu de plus.

 
g tuv J
ab cdef g hi jkl m no pqr s tuv wx y zAB C DE FG HI JKLM NO

Vous devriez faire quelque chose comme ça:

Depuis: one.innerText = g \ n tuv \ n J

Il faudrait le transformer en une expression régulière comme: / g | tuv | J / g

Pour voir le recoupement, copiez et collez le contenu de la classe deux dans ce site et supprimez l’espacement avant “a”, “m” et “C”: http://regexr.com/3eumc

Partie 2

Le problème est que si “tuv” se déplace dans la chaîne 2, il ne serait pas verrouillé avec “g” au-dessus de “u” au-dessus de “J”.

Pour corriger cela “g” au-dessus de “u” au-dessus du problème “J”, nous devrions considérer ceci comme un jeu de données à 2 dimensions pour un plateau de jeu. Cela signifie que la chaîne est transformée en une masortingce (tableau de tableaux), où chaque lettre plus chaque espace est placée dans un emplacement de tableau. Ainsi:

 var masortingx = [ // 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 ]; 

Maintenant, vous pouvez vérifier pour voir si:

 if ((masortingx[0][13] === 'g') && (masortingx[1][12] === 't') && (masortingx[1][13] === 'u') && (masortingx[1][14] === 'v') && (masortingx[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 } 

Partie 3 …

J’ai résolu ce puzzle de recherche masortingcielle. Voir mon jsFiddle à https://jsfiddle.net/briankueck/pern32vv/

Voici l’essentiel de l’apparence du code. Activez le commutateur de débogage sur ce lien jsFiddle pour voir comment il fonctionne. 🙂

 function getMasortingx(cssSelector, canTrim) { // Built by, Clomp! @briankueck http://www.clomp.com var obj = $(cssSelector); if (obj) { var masortingx = obj.text() /* Makes sure that we are selecting 3 lines, not 5 * as the example has a \n after 
\n and before \n
*/ if (canTrim) { masortingx = masortingx.sortingm(); } // Now split those 3 lines. masortingx = masortingx.split(/\n/); /* Trims each array in the masortingx. Note: masortingx[row] is a ssortingng, * but we can treat a ssortingng 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) { masortingx[row] = masortingx[row].replace(/\s/g, space); masortingx[row] = masortingx[row].replace(/\t/g, space); tempMasortingx.push(masortingx[row]); if (masortingx[row].length > maxLength) { maxLength = masortingx[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 charactersToSsortingp = 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 matchingCharInMasortingxOne = masortingxOne[0].indexOf(searchChar); // Now we can find the starting index of character 0 in each row of masortingxTwo: var startIndex = firstCharPosition - matchingCharInMasortingxOne; // This simultaneously scans rows 1, 2 & 3 in both masortingcies. 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 === masortingxTwo.length)) ? true : false; return isFoundInMasortingxTwo; } var cssSelector1 = '.one'; var cssSelector2 = '.two'; var masortingxOne = getMasortingx(cssSelector1, false); var masortingxTwo = getMasortingx(cssSelector2, true); var isFound = masortingxSearch(masortingxOne, masortingxTwo); console.log('Is masortingx 1 in masortingx 2? ', isFound);

Prendre plaisir!

Btw, Merry Christmas Stack Overflow communauté de Clomp!

Eh bien, nous avons déjà de bonnes réponses ici, mais … voici une approche de plus. 🙂

Fondamentalement: filtrez l’entrée, obtenez un motif / une masortingce propre (en supposant qu’il y ait deux espaces au début – corrigez cela!), Testez-le avec un autre modèle (en fait – créez la structure et les tableaux HTML => comparez-les)

La représentation visuelle de ce qui se passe est également présente.

Le code est attrocity, peut et doit être nettoyé (mais ça marche un peu, 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.sortingm().length; masortingx=[]; for(j=0;j'); } $( "table.small tr" ).each(function( index ) { for(j=0;j'+cells[index][j]+''); } }); 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'); } $( "table.big tr" ).each(function( index ) { for(j=0;j'+cells[index][j]+''); } }); //comparing!!! pattern_arr=[]; $("table.small tr").each(function() { pattern_arr.push($(this).children().text().sortingm()) }); function arraysEqual(a1,a2) { /* WARNING: arrays must not contain {objects} or behavior may be undefined */ // console.log(JSON.ssortingngify(a1)+':'+JSON.ssortingngify(a2)); // console.log('________________________________________'); return JSON.ssortingngify(a1)==JSON.ssortingngify(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().sortingm()); 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 
 .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; } 
  
 + +++ + 
 + + ++++ + ++ + + + + ++ +++ + +++ ++ + +++ + ++ + + ++ + + + + ++ 

Le post précédent de @ 2619 montre de l’intérêt pour le problème Bliffoscope . Étant donné que le contenu du texte de div.one et div.two , en police à largeur fixe, ascii art style, sont des images assemblées à partir de + , ce qui signifie un pixel actif , et ” “(espace) inactif . L’idée est de trouver dans quelle position on pourrait placer div.one sur div.two , de sorte que les deux motifs forment plus d’intersections. Je ne considère que l’intersection des coordonnées des pixels actifs de deux images données.

Dans cet exemple, + est remplacé par o pour mettre en évidence les intersections de chaque correspondance. Une version simplifiée utilisant des canvas peut être trouvée ici .

Dans l’ extrait SO ci-dessous et dans la démo JSFiddle , cliquez sur les liens Next et Previous , ou appuyez sur les boutons fléchés du clavier pour parcourir les correspondances.

_main.best_positions() renvoie le nombre d’intersections pour chaque superposition possible, avec n’importe quel degré de tolérance à l’erreur, sortingé par nombre d’intersections (plus de correspondances en premier).

 var PatternFinder; PatternFinder = (function(win, doc, undefined) { 'use ssortingct'; 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_ssortingng: '', context_text_ssortingng: '' }, init: function() { _main.cache.object_text_ssortingng = $(_main.selectors.object_1_pattern).text(); _main.cache.context_text_ssortingng = $(_main.selectors.background_pattern).text(); // Parse our images from the text ssortingngs. _main.serialized_context = _main.serialize_map(_main.cache.context_text_ssortingng); _main.serialized_object = _main.serialize_map(_main.cache.object_text_ssortingng); // 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 ssortingng 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_ssortingng); // 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; } 
  
+ +++ +
+ + ++++ + ++ + + + + ++ +++ + +++ ++ + +++ + ++ + + ++ + + + + ++

Match:

Intersecting coordinates:

Click Next and Previous or use the keyboard arrows to see other possible matches.

L’extrait de code ci-dessous trouve toutes les occurrences du “un” motif dans le “deux” div, comme écrit dans le balisage. Les résultats sont reportés dans la sortie de la console (index de ligne et position en ligne).

Crédits :

  1. Les commentaires de Clomp m’ont aidé à comprendre que la question concernait le modèle de balisage
  2. J’ai emprunté getIndicesOf de cette réponse par 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 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; } 
  
a bcd e
++ + ++ ++++ + ++ + + + a + + ++++ a ++ + + +bcd + a +++ + bcd ++ + +++ e +bcd + + ++ e + + + ++ ++ + e ++++++++++++++++++++++

Votre code jquery ressemblera à ceci. Vous pouvez jouer plus avec cette logique

  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'); } } }); 

Voici le violon: https://jsfiddle.net/ahmadasjad/12eqhs7L/5/

Il y a des idées assez intéressantes dans les articles précédents, j’aime append une approche fonctionnelle qui est plus compacte (elle utilise lodash). L’idée principale est de couper le texte correspondant et de le comparer avec la fenêtre changeante ( coupe ) sur le texte cible. En plus de cette fonction retourne également la position où la correspondance est trouvée de la gauche. Voir le violon de travail :

 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, eg 3 in the example function minTrim(t) { return _.min(t.filter(s=>!!s).map(s=>s.length-_.sortingmStart(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)) } 

Fonction findText peut être utilisée comme ceci:

 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"); 

L’option 2 si la chaîne ne comporte que «+» et la longueur ne dépasse pas 64 caractères, nous pouvons convertir la fonction ci-dessus en correspondance de masque binary. Par exemple, convertir chaque chaîne en chiffre, puis déplacer la chaîne cible, appliquer un masque de recherche (par exemple une fenêtre dans l’exemple ci-dessus) et comparer des nombres. Voir le violon de travail :

 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.toSsortingng(2).length; return false; } 

Juste une suggestion, mais vous pouvez hacher le contenu pour les comparer. Ce code utilise la bibliothèque CryptoJS pour générer le hachage MD5

   

En supposant que le nombre de lignes est le même dans les deux, la solution suivante simplifie la recherche du modèle.

Conditions préalables:

Cette solution nécessite le modèle et la cible à former comme suit:

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

Je pense qu’une simple opération javascript peut faire cela: lire le HTML ligne par ligne et l’append à un tableau. Si nécessaire, je peux également fournir ce code.

Comment ça marche:

Le code décide d’abord de la largeur du pattern , puis continue à rechercher des motifs d’une telle largeur colonne par colonne dans le tableau target . La boucle s’arrête lorsqu’un motif de largeur inférieure est détecté ou qu’une correspondance est trouvée.

Le code:

 // 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; } 

Je pense que cette approche peut être élargie pour éliminer cette hypothèse selon laquelle the number of rows are same in both .

Pour trouver le motif dans une autre chaîne, la position des plus relatifs les uns par rapport aux autres est d’abord trouvée; alors les plus dans la deuxième chaîne sont vérifiés s’ils sont dans les mêmes positions relatives.

La fonction findCoordinates trouve la position des plus dans le modèle par rapport au premier plus dans la chaîne de modèle. Pour le motif,

  + +++ + 

le + dans la rangée supérieure est à (0,0). Le premier + de la deuxième ligne est à (-1,1) car il se trouve une ligne en dessous et un endroit à gauche du premier + . De même, les autres avantages sont respectivement à (0,1), (1,1) et (0,2).

La fonction hasPattern utilise les coordonnées relatives pour vérifier si le motif est présent dans la deuxième chaîne. Pour chaque + de la deuxième chaîne, il vérifie s’il y a d’autres caractères + aux positions correspondantes pour correspondre au modèle. Pour l’exemple, la fonction vérifie si un caractère est un plus. Si c’est un + , alors il vérifie les caractères ci-dessous à gauche, directement en dessous, en bas à droite et deux lignes en dessous. Si ces caractères sont également des plus, la fonction renvoie true.

 function findCoordinates(ssortingng) { var rows = ssortingng.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; } 
 
+ +++ +
+ + ++++ + ++ + + + + ++ +++ + +++ ++ + +++ + ++ + + ++ + + + + ++
 $('.one').diffSsortingng($('.two').html()); 

Cette solution ne fonctionnera pas si le nombre de lignes du test pattern et source pattern est différent.

L’idée est de créer une chaîne de colonnes séquentielles du motif. Ensuite, nous pouvons facilement vérifier si le modèle existe en utilisant indexOf

Exemple, un motif comme celui-ci:

 1 2 3 + + + + + + 

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

entrer la description de l'image ici Voici le violon 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 ssortingng var longestSsortingng = 0; for(var i=0; i 
 
 + +++ + 
 + + ++++ + ++ + + + + ++ +++ + +++ ++ + +++ + ++ + + ++ + + + + ++ 

C’est rapide et moche, encore quelques vérifications d’erreur et optimisations à faire … mais assez pour montrer le concept:

 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)); 

I skipped loading DIV content into pattern/target vars as it seems sortingvial. Also I assumed spaces are also important for pattern, meaning ' + + ' does not match ' +++ '

JSBin is here: http://jsbin.com/kayeyi/edit?js,console

To not overcomplicate things I made some assumptions on the inputs:

  1. Number of lines in inputs are equal
  2. Any empty line from inputs can be omitted
  3. Every non-empty line of inputs should contain whitespace characters at “missing” places
  4. The whitespace character in both inputs is the same and it’s NOT a line break

Besides of collecting data from the DOM the solution goes through following steps:

  1. Both pattern and input are converted into arrays of ssortingngs, each ssortingng for a line. Arrays must have same length ( assumption 1 )
  2. For each pair of lines list of possible matches are collected – list of all indices in input ssortingng on which pattern ssortingng is included
  3. Result lists are flattened into single list and all indices are counted. Now for each possible index we have number of lines where match is successful
  4. Filter the result to leave only indices with maximum count

There is also a working fiddle of the solution

 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; }