2010-03-25 13 views
6

Dies wird in Javascript (jQuery) implementiert werden, aber ich nehme an, die Methode könnte in jeder Sprache verwendet werden.Wie kann ich ein Array sortieren, aber bestimmte Elemente ausschließen (um an der gleichen Position im Array zu bleiben)

Ich habe eine Reihe von Elementen und ich muss eine Sortierung durchführen. Jedoch gibt einige Elemente im Array, die in der gleichen Position (gleichen Index) gehalten werden müssen.

Das Array in Frage ist aus einer Liste von <li> Elemente erstellt und ich verwende .data() Werte an den Listeneintrag als der Wert, nach dem sortiert werden.

Welcher Ansatz wäre hier am besten?

<ul id="fruit"> 
    <li class="stay">bananas</li> 
    <li>oranges</li> 
    <li>pears</li> 
    <li>apples</li> 
    <li class="stay">grapes</li> 
    <li>pineapples</li> 
</ul> 

<script type="text/javascript"> 
    var sugarcontent = new Array('32','21','11','45','8','99'); 
    $('#fruit li').each(function(i,e){ 
     $(this).data('sugar',sugarcontent[i]); 
    }) 
</script> 

ich die Liste mit folgendem Ergebnis ...

<ul id="fruit"> 
     <li class="stay">bananas</li> <!-- score = 32 --> 
     <li>pineapples</li> <!-- score = 99 --> 
     <li>apples</li> <!-- score = 45 --> 
     <li>oranges</li> <!-- score = 21 --> 
     <li class="stay">grapes</li> <!-- score = 8 --> 
     <li>pears</li> <!-- score = 11 --> 
    </ul> 

Dank sortiert werden sollen!

Antwort

6

Algorithmus ist:

  • Extract und sortieren Artikel markiert nicht mit stay
  • Merge stay Artikel und sortiert Artikel

    var sugarcontent = new Array(32, 21, 11, 45, 8, 99); 
    
    var items = $('#fruit li'); 
    
    items.each(function (i) { 
        $(this).data('sugar', sugarcontent[i]); 
        // Show sugar amount in each item text - for debugging purposes 
        if ($(this).hasClass('stay')) 
         $(this).text("s " + $(this).text()); 
        else 
         $(this).text(sugarcontent[i] + " " + $(this).text()); 
    }); 
    
    // Sort sortable items 
    var sorted = $(items).filter(':not(.stay)').sort(function (l, r) { 
        return $(l).data('sugar') - $(r).data('sugar'); 
    }); 
    
    // Merge stay items and sorted items 
    var result = []; 
    var sortedIndex = 0; 
    
    for (var i = 0; i < items.length; i++) 
        if (!$(items[i]).hasClass('stay')) { 
         result.push(sorted[sortedIndex]); 
         sortedIndex++; 
        } 
        else 
         result.push(items[i]); 
    
    // Show result 
    $('#fruit').append(result); 
    
+0

Das ist der Code, der am meisten dem ähnelt, mit dem ich gelandet bin, also habe ich ihn als richtig markiert - ich bin mir sicher Lösung, die von Petersendidit bereitgestellt wird, ist auch gut (obwohl es ungeprüft ist). Vielen Dank! – calumbrodie

0

Das wird nicht funktionieren, wie Bevan darauf hingewiesen, aber ich werde es hier für pädagogische Zwecke verlassen:

$('#fruit li').sort(function(a, b) { 
    return ($(a).hasClass('stay') || $(b).hasClass('stay')) 
     ? 0 : (a.data('sugar') > b.data('sugar') ? 1 : -1); 
}).appendTo('#fruit'); 

Hinweis: Sie müssen den Zucker Daten mit ‚Zucker‘ als Name Argument setzen:

+3

Das Problem bei diesem Ansatz ist, dass die festen Elemente Barrieren zu dieser Art werden - irgendein Gegenstand unter einem festen Punkt wird sich nie darüber bewegen und umgekehrt. – Bevan

+0

Dank Hinweis auf den Syntaxfehler habe ich meinen obigen Beispielcode behoben. – calumbrodie

1

Sie haben Recht damit, dass die Lösung generisch ist und in jeder Entwicklungsumgebung anwendbar ist.

Sie müssen Ihre Elementliste in zwei verschiedene Listen aufteilen - eine, die sortiert werden soll, und eine, die an Ort und Stelle bleibt. Sortieren Sie dann die erste Liste und fusionieren Sie mit der zweiten. Das Schlüsselproblem, dem Sie gegenüberstehen, ist folgendes: Die meisten Sortieralgorithmen (einschließlich QuickSort, die in den meisten Frameworks am häufigsten vorkommt) werden ziemlich unangemessen, wenn Ihre Vergleichsfunktion auf einen externen Zustand (wie Position des Elements) angewiesen ist).

+0

Sollte ich die jQuery-Merge-Funktion verwenden oder die Arrays verketten und resort? Wie stelle ich sicher, dass mein Array von "fixierten" Elementen Vorrang hat, wenn die Indexe identisch sind? Die Lösung, die Sie vorgeschlagen haben, war genau, wie ich es beim ersten Mal versucht habe, aber ich konnte es nicht zum Laufen bringen. Zumindest weiß ich, dass ich auf dem richtigen Weg war.Danke für deinen Beitrag! – calumbrodie

+0

Antwort von @Konstantin scheint mir gut zu sein (mein Javascript ist der Aufgabe nicht gewachsen. +1) – Bevan

3

Dies sollte es tun:

var sugarcontent = new Array('32','21','11','45','8','99'); 
var list = $('#fruit'); 
var lis = list.find('li').each(function(i,e){ 
    $(this).data('score',sugarcontent[i]); 
}); 
var stay = lis.filter('.stay').each(function(){ 
    $(this).data('index',$(this).index()); 
}); 
lis.sort(function(a,b){ 
    return $(b).data('score') - $(a).data('score'); 
}).appendTo(list); 
stay.each(function(){ 
    var index = $(this).data('index'); 
    if (index == 0) { 
     list.prepend(this); 
    } else { 
     lis.filter(':eq('+index+')').insertAfter(this); 
    } 
} 

Dieser speichert den Index der Elemente mit der Klasse bleiben und dann tut es die Art von Partitur und ersetzt dann die Elemente mit der Klasse zurück an der richtigen Stelle bleiben.

Verwandte Themen