2010-03-25 8 views
6

Esto se implementará en Javascript (jQuery) pero supongo que el método podría usarse en cualquier idioma.Cómo puedo ordenar una matriz, pero excluir ciertos elementos (para mantenerlos en la misma posición en la matriz)

Tengo una variedad de elementos y necesito realizar un tipo. Sin embargo, hay algunos elementos en la matriz que deben mantenerse en la misma posición (mismo índice).

La matriz en cuestión es compilación a partir de una lista de elementos <li> y estoy usando valores .data() adjuntos al elemento de la lista como el valor para ordenar.

¿Qué enfoque sería mejor aquí?

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

Quiero la lista ordenada con el siguiente resultado ...

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

Gracias!

Respuesta

6

algoritmo es:

  • Extraer y ordenar los elementos que no aparecen con stay
  • Combinar stay artículos y ordenados artículos

    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

Este es el código que más se parece a lo que terminé, así que lo he marcado como correcto. Estoy seguro de que la solución provista por petersendidit también es buena (aunque no ha sido probada). ¡Gracias! – calumbrodie

0

Esto no funcionará como se señaló Bevan, pero voy a dejarlo aquí con fines educativos:

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

Nota: Es necesario configurar los datos de azúcar con 'azúcar' como argumento de nombre:

.data('sugar', sugarcontent[i]); 
+3

El problema con este enfoque es que los elementos fijos se convierten en barreras al tipo: cualquier elemento debajo de un punto fijo nunca se moverá por encima de él, y viceversa. – Bevan

+0

Gracias señalando el error de sintaxis, he arreglado mi código de ejemplo anterior. – calumbrodie

1

Tiene razón al pensar que la solución es genérica y aplicable a cualquier entorno de desarrollo.

Deberá dividir su lista de elementos en dos listas diferentes: las que se ordenarán y las que se dejarán en su lugar. Luego, ordena la primera lista y fusiona con la segunda.

El problema clave al que se enfrenta es este: la mayoría de los algoritmos de ordenamiento (incluido QuickSort, que es el más común en la mayoría de los marcos) se comportan mal si su función de comparación depende de cualquier estado externo (como la posición del elemento)

+0

¿Debo usar la función de fusión jQuery o concatenar las matrices y resort? ¿Cómo me aseguro de que mi conjunto de elementos 'fijos' tenga prioridad cuando el índice sea el mismo? La solución que propusiste fue exactamente cómo intenté hacer esto la primera vez, pero no pude hacerlo funcionar. Al menos sé que estaba en el camino correcto.¡Gracias por tu contribución! – calumbrodie

+0

Answer by @Konstantin me parece bien (mi Javascript no está a la altura de la tarea. +1) – Bevan

3

Esto debe hacerlo:

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

Esta caja índice de los elementos con la estancia clase y luego se hace el tipo de marcador y luego reemplaza los elementos con la clase se quedan atrás en el lugar correcto.

Cuestiones relacionadas