2015-11-22 12 views
13

Qual è il modo migliore per riorganizzare array in output? Ho bisogno di unire tutte le chiavi di valore (se array o meno) in oggetti che condividono la stessa chiave di nome. C'è qualcosa di simile here, ma questo non risponde alla mia domanda perché anch'io ho array.Unisci oggetti javascript nell'array con la stessa chiave

var array = [ 
    { 
     name: "foo1", 
     value: "val1" 
    }, { 
     name: "foo1", 
     value: [ 
      "val2", 
      "val3" 
     ] 
    }, { 
     name: "foo2", 
     value: "val4" 
    } 
]; 

var output = [ 
    { 
     name: "foo1", 
     value: [ 
      "val1", 
      "val2", 
      "val3" 
     ] 
    }, { 
     name: "foo2", 
     value: [ 
      "val4" 
     ] 
    } 
]; 

Sì, posso scrivere senza fine for loop e più array in mezzo, ma c'è una semplice (r) scorciatoia? Grazie!

+0

è '' array' {name: "foo1", valore: "val1" } 'sta per essere' {nome: "foo1", valore: ["val1"]} '? – BenG

+0

@ BG101 no non è un array ma se questo mi aiuta posso farlo in anticipo – Wagtail

+1

Hai provato a usare il metodo jQuery ext()? O stai cercando di scrivere il tuo script di fusione? Quindi qualcosa del genere forse: 'var newArray = $ .extend ({}, array, output);' – ZachPerkitny

risposta

9

Non so se c'è un modo migliore/più facile, ma questo potrebbe farlo: -

var array = [{ 
 
    name: "foo1", 
 
    value: "val1" 
 
}, { 
 
    name: "foo1", 
 
    value: ["val2", "val3"] 
 
}, { 
 
    name: "foo2", 
 
    value: "val4" 
 
}]; 
 

 
var output = []; 
 

 
array.forEach(function(value) { 
 
    var existing = output.filter(function(v, i) { 
 
    return v.name == value.name; 
 
    }); 
 
    if (existing.length) { 
 
    var existingIndex = output.indexOf(existing[0]); 
 
    output[existingIndex].value = output[existingIndex].value.concat(value.value); 
 
    } else { 
 
    if (typeof value.value == 'string') 
 
     value.value = [value.value]; 
 
    output.push(value); 
 
    } 
 
}); 
 

 
console.dir(output);

+1

Il mio 'key' e' valore' nome sono diversi. e mi sto confondendo perché qui il nome 'value' nell'oggetto di input è' value' e il nome del parametro che hai preso nel ciclo 'forEach' è anche chiamato valore. Per favore, chiarisci la mia confusione. Grazie. –

+0

Grazie per l'idea – Rajiv

3

Utilizzando lodash

var array = [{name:"foo1",value:"val1"},{name:"foo1",value:["val2","val3"]},{name:"foo2",value:"val4"}]; 

function mergeNames (arr) { 
    return _.chain(arr).groupBy('name').mapValues(function (v) { 
     return _.chain(v).pluck('value').flattenDeep(); 
    }).value(); 
} 

console.log(mergeNames(array)); 
1

Prova questo:

var array = [{name:"foo1",value:"val1"},{name:"foo1",value:["val2","val3"]},{name:"foo2",value:"val4"},{name:"foo2",value:"val5"}]; 
 

 
for(var j=0;j<array.length;j++){ 
 
    var current = array[j]; 
 
    for(var i=j+1;i<array.length;i++){ 
 
    if(current.name = array[i].name){ 
 
     if(!isArray(current.value)) 
 
     current.value = [ current.value ]; 
 
     if(isArray(array[i].value)) 
 
     for(var v=0;v<array[i].value.length;v++) 
 
      current.value.push(array[i].value[v]); 
 
     else 
 
     current.value.push(array[i].value); 
 
     array.splice(i,1); 
 
     i++; 
 
    } 
 
    } 
 
} 
 

 
function isArray(myArray) { 
 
    return myArray.constructor.toString().indexOf("Array") > -1; 
 
} 
 

 
document.write(JSON.stringify(array));

+0

questo è infallibile, ma è il metodo tradizionale forza bruta che sto cercando di aggirare. – Wagtail

+1

Sì, ma non ho usato loop "infiniti" :-), ho usato solo due cicli e, cosa più importante, ho lavorato direttamente alla variabile 'array', eliminando la necessità di un'altra variabile' output' che rende più efficiente la memoria. Tuttavia, mi sono piaciute anche le due risposte di BG101 e Hunan, quindi le ho sottoposte a upvoted. –

4

Ecco un altro modo per raggiungere questo obiettivo:

var output = array.reduce(function(o, cur) { 

    // Get the index of the key-value pair. 
    var occurs = o.reduce(function(n, item, i) { 
    return (item.name === cur.name) ? i : n; 
    }, -1); 

    // If the name is found, 
    if (occurs >= 0) { 

    // append the current value to its list of values. 
    o[occurs].value = o[occurs].value.concat(cur.value); 

    // Otherwise, 
    } else { 

    // add the current item to o (but make sure the value is an array). 
    var obj = {name: cur.name, value: [cur.value]}; 
    o = o.concat([obj]); 
    } 

    return o; 
}, []); 
0

Utilizzando ridurre:

var mergedObj = array.reduce((acc, obj) => { 
    if (acc[obj.name]) { 
     acc[obj.name].value = acc[obj.name].value.isArray ? 
     acc[obj.name].value.concat(obj.value) : 
     [acc[obj.name].value].concat(obj.value); 

    } else { 
     acc[obj.name] = obj; 
    } 

    return acc; 
}, {}); 

let output = []; 
for (let prop in mergedObj) { 
    output.push(mergedObj[prop]) 
} 
Problemi correlati