Zeilen mit identischen Werten in einer Tabelle markieren

  • Ich habe einen einfachen Algorithmus, der Tabellenzeilen mit identischen Einträgen blau markiert. Das Problem ist, dass diese Lösung viel Zeit in Anspruch nimmt.

    Hat jemand eine Idee, wie Sie die Geschwindigkeit verbessern können?

     $(document).ready(function(){
       var tableRows = $("#sortable tbody tr");
       tableRows.each(function(n){
          var id = $(this).attr('id'); 
          var example = $(this).children('#example').children('#content').html(); 
    
          tableRows.each(function(n){
             if($(this).attr('id') != id)
             {
                if ($(this).children('#example').children('#content').html() == example)
                {
                   $(this).css('backgroundColor', 'azure');
                }
             }
          });
       });
    });
     

    Meine Tabelle sieht folgendermaßen aus:

     <table align="center" id="sortable">
       <thead>
          <tr bgcolor="orange">
             <th>Digitcode</th>
          </tr>
       </thead>
    
       <tbody>
          <tr id="1">
             <th id="example" class="data"><div contenteditable id="content">test</div></th>
          </tr>
       </tbody>
    </table>
     
    16 January 2016
    QuillNaveenBhat
2 answers
  • 1,5 Sekunden für ~ 1000 Reihen erscheinen mir immer noch sehr hoch. Ihr Algorithmus ist O(n^2).

    Wir können den Weg besser machen.

     $(document).ready(function() {
        var tableRows = $("#sortable tbody tr"),
            // we know exactly how large to make it, so don't use []
            htmlStrings = new Array(tableRows.length),
            i, j, current, comparing;
    
        for (i = 0; i < tableRows.length; i++) {
            current = htmlStrings[i];
            // get each innerHTML just once
            if (!current) {
                current = {
                    html: tableRows.get(i).innerHTML,
                    isDup: false
                };
                htmlStrings[i] = current;
            }
    
            // if we already know it's a dup, so we're done
            if (current.isDup) continue;
    
            // start j at i+1 since we've already looked at the previous i rows
            for (j = i + 1; j < tableRows.length; j++) {
                // could stay DRY and put this into a function;
                // doing so may decrease performance (not benchmarked)
                comparing = htmlStrings[j];
                if (!comparing) {
                    comparing = {
                        html: tableRows.get(j).innerHTML,
                        isDup: false
                    };
                    htmlStrings[j] = comparing;
                }
    
                if (comparing.isDup) continue;
    
                // It comes to this: we must actually compare now.
                if (current.html === comparing.html) {
                    current.isDup = true;
                    comparing.isDup = true;
    
                    // mark it
                    tableRows.eq(j).css('backgroundColor', 'red');
                }
            }
    
            if (current.isDup) {
                // mark it
                tableRows.eq(i).css('backgroundColor', 'red');
            }
    
        }
    });​
     
    1. Rufen Sie .html() nicht mehrmals in einer Zeile auf.
    2. Wenn eine Zeile bereits als Duplikat markiert wurde, gibt es keinen Grund, sie weiterzuverarbeiten, noch ist eine der Zeilen, von denen es ein Duplikat ist.
    3. Betrachtet man n th -Zeile haben wir uns bereits alle vorherigen n-1 -Zeile angesehen, so dass es auch keinen Grund gibt, diese weiter zu betrachten.
    4. Verwenden Sie ein reguläres for Schleife statt einer forEach, die eine Funktion übernimmt.
    5. Verwenden Sie .innerHTML anstelle von .html().
    6. Verwenden Sie === anstatt ==.

    Für Leistungstests gehe ich davon aus, dass der Textinhalt jeder Zeile eine zufällige ganze Zahl ist. ? [0, 9999]. Dies macht es leicht, eine große Anzahl zufälliger Zeilen zu erzeugen, die eine angemessene Wahrscheinlichkeit für Kollisionen haben:

    var arr = [];
    for (var i=0; i<1000; i++)
    {
        arr.push('<tr id="' + i + '"><th class="data"><div contenteditable>' + (~~(Math.random()*10000)) + '</div></th></tr>');
    }
    console.log(arr.join('\n'));
     

    Ursprüngliche Antwort Code, O(n^2): jsFiddle

    Optimiert, O(n log n) Ich denke : jsFiddle

    jsPerf-Vergleich: 1k Zeilen | 10.000 Zeilen

    Schauen Sie, wie viel schneller das ist!

    19 March 2012
    Matt Ball
  • Die Sache var $rowsToMark = $(); hat nicht funktioniert. Nichts wurde markiert.

    Jetzt vergleiche ich die ganzen Zeilen und nicht alle darin enthaltenen Spalten.

    Die Ladezeit meiner Site beträgt jetzt 1,5 Sekunden. Vorher waren es 5,5 Sekunden.

     $(document).ready(function() {
       var tableRows = $("#sortable tbody tr");
    
       tableRows.each(function(n){
          var id = this.id;
          var row = $(this).html();
    
          tableRows.each(function(n){
             var $this;
    
             if(this.id != id){
                $this = $(this);
    
                if ($this.html() == row){
                   $this.css('backgroundColor', 'azure');
                }
              }
           });
       });
    });
     
    24 June 2014
    Jamal