2015-11-22 13 views
13

Jaki jest najlepszy sposób na reorganizację array na output? Muszę scalić wszystkie klucze wartości (niezależnie od tego, czy są to tablice) w obiektach o tym samym kluczu nazwy. Jest coś podobnego: here, ale to nie odpowiada na moje pytanie, ponieważ mam również tablice.Scal obiekty javascript w tablicy z tym samym kluczem

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" 
     ] 
    } 
]; 

Tak, mogę napisać nieograniczone for pętle i kilka tablic pomiędzy, ale jest tam prosty (r) skrót? Dzięki!

+0

jest '' {array' nazwę: "foo1", wartość "val1" } 'going to be {name:" foo1 ", value: [" val1 "]}? – BenG

+0

@ BG101 Nie to nie jest tablica, ale jeśli to pomoże, mogę to zrobić wcześniej. – Wagtail

+1

Czy próbowałeś używać metody extend() jQuery? Czy próbujesz napisać własny skrypt scalający? Może więc coś takiego: 'var newArray = $ .extend ({}, array, output);' – ZachPerkitny

Odpowiedz

9

Nie wiem, czy istnieje lepszy/łatwiejszy sposób, ale byłoby to zrobić: -

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

Moje nazwy "klucza" i "wartości" są różne. i jestem zdezorientowany, ponieważ tutaj nazwa 'value' w obiekcie wejściowym to' value', a nazwa parametru, którą wziąłeś w pętli 'forEach' jest również nazywana wartością. Proszę wyjaśnić moje zamieszanie. Dzięki. –

+0

Dzięki za pomysł – Rajiv

3

Korzystanie 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

Spróbuj:

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

jest to niezawodny, ale jest to tradycyjna metoda brutalnej siły, którą próbuję ominąć. – Wagtail

+1

Tak, ale nie używałem pętli "nieskończonych" :-), użyłem tylko dwóch pętli i, co ważniejsze, pracowałem bezpośrednio na zmiennej 'array' eliminując potrzebę kolejnej zmiennej" output ", co czyni ją bardziej wydajną pod względem pamięci. Jednak podobały mi się również dwie odpowiedzi od BG101 i Hunana, więc przegłosowałem je. –

4

Oto kolejny sposób na osiągnięcie tego celu:

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

Korzystanie zmniejszyć:

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]) 
} 
Powiązane problemy