2010-09-29 10 views
5

que tiene una matriz de elementos de la siguiente manera en Javascript:Javascript gama especie naturales/objeto y mantener la asociación de índices

var users = Array(); 

users[562] = 'testuser3'; 
users[16] = 'testuser6'; 
users[834] = 'testuser1'; 
users[823] = 'testuser4'; 
users[23] = 'testuser2'; 
users[917] = 'testuser5'; 

que hay que solucionar esa matriz para obtener el siguiente resultado:

users[834] = 'testuser1'; 
users[23] = 'testuser2'; 
users[562] = 'testuser3'; 
users[823] = 'testuser4'; 
users[917] = 'testuser5'; 
users[16] = 'testuser6'; 

Observe cómo se ordena por el valor de la matriz y la asociación de valor a índice se mantiene después de ordenar la matriz (que es crítica). He buscado una solución a esto, intenté hacerlo, pero choqué contra una pared.

Por cierto, soy consciente de que técnicamente esto no es una matriz, ya que eso significaría que los índices siempre están iterando de 0 a n, donde n + 1 es el número de conteo que va n. Sin importar cómo lo defina, el requisito para el proyecto sigue siendo el mismo. Además, si hace una diferencia, NO estoy usando jquery.

Respuesta

2

Usando las ideas de los comentarios, se me ocurrió con la siguiente solución. La función naturalSort es algo que encontré en google y lo modifiqué para ordenar una matriz multidimensional. Básicamente, hice que los usuarios dispusieran una matriz multidimensional con el primer índice como ID de usuario y el segundo índice como nombre de usuario. Por lo tanto:

users[0][0] = 72; 
users[0][1] = 'testuser4'; 
users[1][0] = 91; 
users[1][1] = 'testuser2'; 
users[2][0] = 12; 
users[2][1] = 'testuser8'; 
users[3][0] = 3; 
users[3][1] = 'testuser1'; 
users[4][0] = 18; 
users[4][1] = 'testuser7'; 
users[5][0] = 47; 
users[5][1] = 'testuser3'; 
users[6][0] = 16; 
users[6][1] = 'testuser6'; 
users[7][0] = 20; 
users[7][1] = 'testuser5'; 

que clasificaron a continuación la matriz para obtener el siguiente resultado:

users_sorted[0][0] = 3; 
users_sorted[0][1] = 'testuser1'; 
users_sorted[1][0] = 91; 
users_sorted[1][1] = 'testuser2'; 
users_sorted[2][0] = 47; 
users_sorted[2][1] = 'testuser3'; 
users_sorted[3][0] = 72; 
users_sorted[3][1] = 'testuser4'; 
users_sorted[4][0] = 20; 
users_sorted[4][1] = 'testuser5'; 
users_sorted[5][0] = 16; 
users_sorted[5][1] = 'testuser6'; 
users_sorted[6][0] = 18; 
users_sorted[6][1] = 'testuser7'; 
users_sorted[7][0] = 12; 
users_sorted[7][1] = 'testuser8'; 

El código para hacer esto es el siguiente:

function naturalSort(a, b) // Function to natural-case insensitive sort multidimensional arrays by second index 
{ 

    // setup temp-scope variables for comparison evauluation 
    var re = /(-?[0-9\.]+)/g, 
     x = a[1].toString().toLowerCase() || '', 
     y = b[1].toString().toLowerCase() || '', 
     nC = String.fromCharCode(0), 
     xN = x.replace(re, nC + '$1' + nC).split(nC), 
     yN = y.replace(re, nC + '$1' + nC).split(nC), 
     xD = (new Date(x)).getTime(), 
     yD = xD ? (new Date(y)).getTime() : null; 
    // natural sorting of dates 
    if (yD) 
     if (xD < yD) return -1; 
     else if (xD > yD) return 1; 
    // natural sorting through split numeric strings and default strings 
    for(var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) { 
     oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc]; 
     oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc]; 
     if (oFxNcL < oFyNcL) return -1; 
     else if (oFxNcL > oFyNcL) return 1; 
    } 
    return 0; 
} 

// Set values for index 
    var users = Array(); 
    var temp = Array(); 

    users.push(Array('72', 'testuser4')); 
    users.push(Array('91', 'testuser2')); 
    users.push(Array('12', 'testuser8')); 
    users.push(Array('3', 'testuser1')); 
    users.push(Array('18', 'testuser7')); 
    users.push(Array('47', 'testuser3')); 
    users.push(Array('16', 'testuser6')); 
    users.push(Array('20', 'testuser5')); 

// Sort the array 
    var users_sorted = Array(); 
    users_sorted = users.sort(naturalSort); 
+0

Hola, me alegra que hayas encontrado una respuesta que funcione, pero te animo a echar un vistazo rápido a [mi respuesta] (http://stackoverflow.com/questions/3824392/javascript-natural-sort-array-object -and-maintain-index-association/3824938 # 3824938) (¡Llegué un poco tarde al juego!) arriba. La comparación de cadenas está integrada en JavaScript, y es posible que en general sea una solución más limpia. – s4y

+0

También debe buscar en el conjunto y los literales de objeto (solo los menciono brevemente en mi respuesta). Podrías crear esa matriz 'users' en tu código de ejemplo mucho más rápido:' var users = [['72', 'testuser4'], ['91', 'testuser2'], ...] ' – s4y

+0

Gracias por el aviso, se ve más limpio. ¿Admite la clasificación de casos naturales? Eso es lo que hizo que mi código fuera un poco más descuidado. – user396404

3

No puede solicitar matrices como esta en Javascript. Su mejor opción es hacer un mapa para la orden.

order = new Array(); 
order[0] = 562; 
order[1] = 16; 
order[2] = 834; 
order[3] = 823; 
order[4] = 23; 
order[5] = 917; 

De esta manera, puede tener cualquier orden que desee independientemente de las teclas en la matriz original. Para ordenar su matriz, utilice una función de clasificación personalizada .

order.sort(function(a, b) { 
    if (users[a] < users[b]) return -1; 
    else if (users[a] > users[b]) return 1; 
    else return 0; 
}); 

for (var i = 0; i < order.length; i++) { 
    // users[ order[i] ] 
} 

[Demo]

22

El orden de los elementos de una matriz se define por el índice. Así que incluso si especifica los valores en un orden diferente, los valores siempre se almacenan en el orden de sus índices y los índices definidos son undefined:

> var arr = []; 
> arr[2] = 2; 
> arr[0] = 0; 
> arr 
[0, undefined, 2] 

Ahora bien, si desea almacenar el par de índice y valor, se necesita una estructura de datos diferente, tal vez un conjunto de matriz de la siguiente manera:

var arr = [ 
    [562, 'testuser3'], 
    [16, 'testuser6'], 
    [834, 'testuser1'], 
    [823, 'testuser4'], 
    [23, 'testuser2'], 
    [917, 'testuser5'] 
]; 

esto puede ser ordenada con esta función de comparación:

function cmp(a, b) { 
    return a[1].localeCompare(b[1]); 
} 
arr.sort(cmp); 

El resultado es esta matriz:

[ 
    [834, 'testuser1'], 
    [23, 'testuser2'], 
    [562, 'testuser3'], 
    [823, 'testuser4'], 
    [917, 'testuser5'], 
    [16, 'testuser6'] 
] 
0

Array.prototype.sort() tiene una función de comparación personalizado opcional - por lo que si vuelca toda su users en una matriz de esta manera [ [562, "testuser3"], [16, "testuser6"] ... etc.]

Entonces sort esta matriz con la siguiente función :

function(comparatorA, comparatorB) { 
    var userA = comparatorA[1], userB = comparatorB[1] 
    if (userA > userB)  return 1; 
    if (userA < userB)  return -1; 
    if (userA === userB) return 0; 
} 

A continuación, reconstruya su objeto users. (Lo que le hará perder su clasificación). O bien, conserve los datos en la nueva matriz ordenada de matrices, si eso funciona para su aplicación.

7

Si entiendo la pregunta correctamente, está utilizando matrices de una manera que no están destinadas a ser utilizadas.De hecho, el estilo de inicialización

// Don't do this! 
var array = new Array(); 
array[0] = 'value'; 
array[1] = 'value'; 
array[2] = 'value'; 

muestra aspectos erróneos sobre la naturaleza y el propósito de las matrices. Una matriz es una lista ordenada de elementos indexados desde cero. La forma correcta de crear una matriz es una matriz con literal:

var array = [ 
    'value', 
    'value', 
    'value' 
] 

Los índices están implicadas en base a la orden de los artículos se especifican. Crear una matriz y establecer users[562] = 'testuser3'implica que hay al menos 562 otros usuarios en la lista, y que usted tiene una razón para conocer la 563a en este momento.

En su caso, el índice es de datos, y no representa el orden de los elementos en el conjunto. Lo que estás buscando es un mapa o diccionario, representada en JavaScript por un objeto liso:

var users = { 
    562: 'testuser3', 
    16: 'testuser6', 
    834: 'testuser1', 
    823: 'testuser4', 
    23: 'testuser2', 
    917: 'testuser5' 
} 

Ahora su conjunto no tiene un orden, pero tiene teclas significativas. A partir de aquí, puede seguir galambalazs's advice para crear una matriz de claves del objeto:

var userOrder; 
if (typeof Object.keys === 'function') { 
    userOrder = Object.keys(users); 
} else { 
    for (var key in users) { 
     userOrder.push(key); 
    } 
} 

... Luego, ordenar que:

userOrder.sort(function(a, b){ 
    return users[a].localeCompare(users[b]); 
}); 

Here's a demo

+0

@Gumbo ¡Estoy de acuerdo! ¿En dónde mi respuesta difiere con eso? – s4y

+0

No importa. De alguna manera, pensé que estabas tratando de ordenar las propiedades de un objeto. – Gumbo

1

que haría uso de mapa una vez para crear una nueva matriz de usuarios, y una segunda vez para devolver la cadena que desea de la nueva matriz.

var users= []; 
users[562]= 'testuser3'; 
users[16]= 'testuser6'; 
users[834]= 'testuser1'; 
users[823]= 'testuser4'; 
users[23]= 'testuser2'; 
users[917]= 'testuser5'; 

var u2= []; 
users.map(function(itm, i){ 
    if(itm){ 
     var n= parseInt(itm.substring(8), 10); 
     u2[n]= i; 
    } 
}); 
u2.map(function(itm, i){ 
    return 'users['+itm+']= testuser'+i; 
}).join('\n'); 

/*returned value: (String) 
users[834]= testuser1 
users[23]= testuser2 
users[562]= testuser3 
users[823]= testuser4 
users[917]= testuser5 
users[16]= testuser6 
*/ 

Si quiere evitar huecos. utilice un filtro simple en la salida-

u2.map(function(itm, i){ 
    return 'users['+itm+']= testuser'+i; 
}).filter(function(itm){return itm}).join('\n'); 
1

Las matrices dispersas generalmente causan problemas. Es mejor que pares de valores clave de verano en una matriz como objetos (esta técnica es también válida JSON):

users = [{ 
    "562": "testuser3" 
},{ 
    "16": "testuser6" 
}, { 
    "834": "testuser1" 
}, { 
    "823": "testuser4" 
}, { 
    "23": "testuser2" 
}, { 
    "917": "testuser5" 
}]; 

Como se sugiere, se puede utilizar un bucle para asignar la función de clasificación en la matriz.