Mentre map
è una soluzione adeguata per selezionare "colonne" da un elenco di oggetti, ha un aspetto negativo. Se non viene verificato esplicitamente l'esistenza delle colonne, verrà generato un errore e (nella migliore delle ipotesi) fornito undefined
. Opterei per una reduce
soluzione, che può semplicemente ignorare la proprietà o persino impostarti con un valore predefinito.
function getFields(list, field) {
// reduce the provided list to an array only containing the requested field
return list.reduce(function(carry, item) {
// check if the item is actually an object and does contain the field
if (typeof item === 'object' && field in item) {
carry.push(item[field]);
}
// return the 'carry' (which is the list of matched field values)
return carry;
}, []);
}
esempio jsbin
Ciò funzionerebbe anche se uno degli elementi nell'elenco fornito non è un oggetto o non contiene il campo.
Può anche essere reso più flessibile negoziando un valore predefinito nel caso in cui un articolo non sia un oggetto o non contenga il campo.
function getFields(list, field, otherwise) {
// reduce the provided list to an array containing either the requested field or the alternative value
return list.reduce(function(carry, item) {
// If item is an object and contains the field, add its value and the value of otherwise if not
carry.push(typeof item === 'object' && field in item ? item[field] : otherwise);
// return the 'carry' (which is the list of matched field values)
return carry;
}, []);
}
esempio jsbin
Questo sarebbe lo stesso con map, poiché la lunghezza dell'array restituito sarebbe la stessa dell'array fornito. (Nel qual caso a map
è leggermente più economico di a reduce
):
function getFields(list, field, otherwise) {
// map the provided list to an array containing either the requested field or the alternative value
return list.map(function(item) {
// If item is an object and contains the field, add its value and the value of otherwise if not
return typeof item === 'object' && field in item ? item[field] : otherwise;
}, []);
}
esempio jsbin
E poi c'è la soluzione più flessibile, quella che ti consente di passare da un comportamento all'altro semplicemente fornendo un valore alternativo.
function getFields(list, field, otherwise) {
// determine once whether or not to use the 'otherwise'
var alt = typeof otherwise !== 'undefined';
// reduce the provided list to an array only containing the requested field
return list.reduce(function(carry, item) {
// If item is an object and contains the field, add its value and the value of 'otherwise' if it was provided
if (typeof item === 'object' && field in item) {
carry.push(item[field]);
}
else if (alt) {
carry.push(otherwise);
}
// return the 'carry' (which is the list of matched field values)
return carry;
}, []);
}
esempio jsbin
Mentre gli esempi sopra (si spera) fanno luce sul modo in cui funziona, accorciamo un po 'la Array.concat
funzione utilizzando la funzione.
function getFields(list, field, otherwise) {
var alt = typeof otherwise !== 'undefined';
return list.reduce(function(carry, item) {
return carry.concat(typeof item === 'object' && field in item ? item[field] : (alt ? otherwise : []));
}, []);
}
esempio jsbin
var foos = objArray.pluck("foo");
.