2010-10-28 10 views
9

versión corta: Estoy buscando el equivalente JavaScript de Perliteración sobre un objeto JavaScript en orden de clasificación basado en particular, valor clave de un objeto secundario

for my $key (sort { $hash{$a}{foo} cmp $hash{$b}{foo} } keys %hash) { 
    # do something with $key 
} 

más detalle:

tengo una objeto JSON que consiste en un grupo de otros objetos JSON que tienen propiedades idénticas entre sí, como un hash de hashes en Perl: por ejemplo:

var peopleobj = { 
    "0291" : { "Forename" : "Jeremy", "Surname" : "Dyson" }, 
    "0398" : { "Forename" : "Billy", "Surname" : "Bunter" }, 
    "6714" : { "Forename" : "Harry", "Surname" : "Peterson" }, 
    "9080" : { "Forename" : "Barry", "Surname" : "Mainwaring"} 
} 

Quiero iterar a través de los objetos i n peopleobj en orden de los valores de los apellidos, por ejemplo, para imprimir los nombres en orden de apellido. Las soluciones simples de JavaScript o jQuery funcionarán en el contexto en el que se está implementando.

Gracias de antemano por su valioso tiempo.

+0

Muchas gracias Daniel - ¡eso es realmente útil! – Jonah

+1

Solo un detalle: esa cosa no se llama objeto JSON, sino un objeto JavaScript; JSON es solo una notación de un objeto de JavaScript. –

+0

Gracias por la aclaración, muy apreciada. ¡Debidamente observado! – Jonah

Respuesta

9

Pregunta interesante ... Una solución simple de JavaScript es crear un índice para sus objetos en una matriz separada, basada en la propiedad 'Surname'. Algo como esto :

var peopleobj = { 
    "0291" : { "Forename" : "Jeremy", "Surname" : "Dyson" }, 
    "0398" : { "Forename" : "Billy", "Surname" : "Bunter" }, 
    "6714" : { "Forename" : "Harry", "Surname" : "Peterson" }, 
    "9080" : { "Forename" : "Barry", "Surname" : "Mainwaring" } 
}; 

var index = []; 

// build the index 
for (var x in peopleobj) { 
    index.push({ 'key': x, 'Surname': peopleobj[x]['Surname'] }); 
} 

// sort the index 
index.sort(function (a, b) { 
    var as = a['Surname'], 
     bs = b['Surname']; 

    return as == bs ? 0 : (as > bs ? 1 : -1); 
}); 

Ahora usted sería capaz de iterar sobre su index matriz:

for (var i = 0; i < index.length; i++) { 
    console.log(peopleobj[index[i]['key']]['Surname']); 
} 

Resultado (Probado en la consola de Firebug):

Bunter 
Dyson 
Mainwaring 
Peterson 

Usted puede quiero envolver esto en algún tipo de objeto Iterator reutilizable, aunque sería difícil de obtener tan escueto como Perl:

// Our reusable Iterator class: 
function MyIterator (o, key) { 
    this.index = []; 
    this.i = 0; 
    this.o = o; 

    for (var x in o) { 
     this.index.push({ 'key': x, 'order': o[x][key] }); 
    } 

    this.index.sort(function (a, b) { 
     var as = a['order'], 
      bs = b['order']; 

     return as == bs ? 0 : (as > bs ? 1 : -1); 
    }); 

    this.len = this.index.length; 
} 

MyIterator.prototype.next = function() { 
    return this.i < this.len ? 
      this.o[this.index[this.i++]['key']] : 
      null; 
}; 

A continuación, utilice la siguiente manera:

// Our JavaScript object: 
var peopleobj = { 
    "0291" : { "Forename" : "Jeremy", "Surname" : "Dyson" }, 
    "0398" : { "Forename" : "Billy", "Surname" : "Bunter" }, 
    "6714" : { "Forename" : "Harry", "Surname" : "Peterson" }, 
    "9080" : { "Forename" : "Barry", "Surname" : "Mainwaring" } 
}; 

// Build the Iterator object, using the 'Surname' field: 
var surnameIter = new MyIterator(peopleobj, 'Surname'); 

// Iterate: 
var i; 

while (i = surnameIter.next()) { 
    console.log(i['Surname'] + ' ' + i['Forename']); 
} 

Resultado:

Bunter Billy 
Dyson Jeremy 
Mainwaring Barry 
Peterson Harry 

Es posible que desee utilizar el método hasOwnProperty() para asegurar que las propiedades pertenecen a su objeto y no son heredados de Object.prototype:

for (var x in peopleobj) { 
    if (peopleobj.hasOwnProperty(x)) { 
     index.push({ 'key': x, 'Surname': peopleobj[x]['Surname'] }); 
    } 
} 
+2

+1. Buena respuesta, aunque se supone que la función de comparación pasada a 'sort()' devuelve un número, no un booleano. Sugeriría algo como 'function (a, b) {var as = a.Surname., Bs = b.Surname; regresar como == bs? 0: (como> bs? 1: -1); } ' –

+0

@Tim: Gracias, tienes razón. Actualizaré mi respuesta. –

+0

Esta es una gran solución gracias por la explicación. Utilicé esta cadena plus convertida a fecha en las funciones de clasificación y obtuve exactamente lo que necesitaba. – Akers

Cuestiones relacionadas