2015-11-22 313 views
13

array重組爲output的最佳方法是什麼?我需要將所有的值鍵(不管是否是數組)合併到共享相同名稱鍵的對象中。有類似的here,但這並不能回答我的問題,因爲我也有數組。用相同的鍵合併陣列中的javascript對象

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

是的,我可以寫在無盡之間循環for和幾個陣列,但有一個簡單的(R)快捷鍵?謝謝!

+0

是''array' {名: 「foo1」,值: 「VAL1」 }'要成爲'{name:「foo1」,value:[「val1」]}'? – BenG

+0

@ BG101不,它不是一個數組,但如果這有幫助,我可以事先做好 – Wagtail

+1

您是否嘗試過使用jQuery的extend()方法?或者你正在嘗試編寫自己的合併腳本?所以這樣的事情可能是這樣的:'var newArray = $ .extend({},array,output);' – ZachPerkitny

回答

9

不知道是否有一個更好/更簡單的方法,但這會做到這一點: -

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

我的''key'和'value'是不同的。並且我感到困惑,因爲這裏輸入對象中的'value'名稱是'value',並且'forEach'循環中的參數名稱也被命名爲value。請弄清楚我的困惑。謝謝。 –

+0

感謝您的想法 – Rajiv

3

使用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

試試這個:

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

這是萬無一失的,但它是我試圖解決的傳統的蠻力方法。 – Wagtail

+1

是的,但我沒有使用「無盡的」循環:-),我只使用了兩個循環,更重要的是,我直接在'array'變量上工作,消除了另外一個'output'變量的需要,這使得內存效率更高。不過,我也喜歡BG101和湖南的兩個答案,所以我提出了他們的提議。 –

4

這裏是實現這一目標的另一種方式:

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

使用減少:

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]) 
} 
相關問題