[英]Improve Array transformation in Javascript
假設我有一個如下所示的輸入數組
var inputArray = [
{a: 1, b: 1, c: 1, d: 1, value: 1, rank: 1},
{a: 1, b: 1, c: 1, d: 1, value: 2, rank: 2},
{a: 1, b: 1, c: 1, d: 1, value: 3, rank: 3},
{a: 1, b: 1, c: 1, d: 1, value: 4, rank: 4},
{a: 1, b: 1, c: 1, d: 1, value: 5, rank: 5},
{a: 1, b: 2, c: 1, d: 1, value: 1, rank: 1},
{a: 1, b: 2, c: 1, d: 1, value: 2, rank: 2},
{a: 1, b: 2, c: 1, d: 1, value: 3, rank: 3},
{a: 1, b: 2, c: 1, d: 1, value: 4, rank: 4},
{a: 1, b: 2, c: 1, d: 1, value: 5, rank: 5}
]
我想我的轉變inputArray
以下outputArray
var outputArray = [
{
a: 1,
b: 1,
c: 1,
d: 1,
values:{
"1":{value: 1},
"2":{value: 2},
"3":{value: 3},
"4":{value: 4},
"5":{value: 5}
}
},
{
a: 1,
b: 2,
c: 1,
d: 1,
values:{
"1":{value: 1},
"2":{value: 2},
"3":{value: 3},
"4":{value: 4},
"5":{value: 5}
}
}
]
這意味着,我需要為a
, b
, c
和d
相同屬性創建一個字典,其中屬性rank
的值是字典的鍵,字典的值是唯一屬性為value
的object
。
我們假設inputArray
不會根據a
, b
, c
和d
的組合進行排序。 所以,我的方法是這樣的,
(function(){ var inputArray = [ {a: 1, b: 1, c: 1, d: 1, value: 1, rank: 1}, {a: 1, b: 1, c: 1, d: 1, value: 2, rank: 2}, {a: 1, b: 1, c: 1, d: 1, value: 3, rank: 3}, {a: 1, b: 1, c: 1, d: 1, value: 4, rank: 4}, {a: 1, b: 1, c: 1, d: 1, value: 5, rank: 5}, {a: 1, b: 2, c: 1, d: 1, value: 1, rank: 1}, {a: 1, b: 2, c: 1, d: 1, value: 2, rank: 2}, {a: 1, b: 2, c: 1, d: 1, value: 3, rank: 3}, {a: 1, b: 2, c: 1, d: 1, value: 4, rank: 4}, {a: 1, b: 2, c: 1, d: 1, value: 5, rank: 5} ] var temp = inputArray.sort(function(valA, valB){ if(valA.a === valB.a){ if(valA.b === valB.b){ if(valA.c === valB.c){ return valA.d < valB.d; } return valA.c < valB.c; } return valA.b < valB.b; } return valA.a < valB.a; }); var outputArray = [], currentIndex = 0; for(var i = 0; i < inputArray.length; i++){ if(i > 0 && isConfigurationSame(inputArray[i], inputArray[i-1])){ outputArray[currentIndex-1].values[inputArray[i].rank] = { value: inputArray[i].value } } else{ outputArray.push(mapToOutputArrayObject(inputArray[i])); currentIndex++; } } console.log(outputArray); function isConfigurationSame(A, B) { return Aa === Ba && Ab === Bb && Ac === Bc && Ad === Bd; } function mapToOutputArrayObject(val){ var row = {}; row['a'] = val.a; row['b'] = val.b; row['c'] = val.c; row['d'] = val.d; row['values'] = {}; row.values[val.rank] = { value: val.value } return row; } }());
但問題是,如果輸入數組的長度很大,這個東西真的會有更多的時間。 這種多標准排序也需要很長時間。
是否有更好的方法可以用更少的時間更有效地完成結果?
感謝您的時間和耐心。
更新: a
, b
, c
和d
可以是整數或null
。
您可以創建一個哈希表並根據a,b,c和d生成唯一鍵:
const hash = {};
for(const { a, b, c, d, value, rank } of array) {
const key = JSON.stringify([a, b, c, d]); // generate a unique, but not random key
if(hash[key]) { // check if it already exists,
hash[key].values[rank] = value; // merge
} else {
hash[key] = { // create a new entry
a, b, c, d,
values: { [rank]: value },
};
}
}
const result = Object.values(hash); // turn the object into an array
那就是O(n),它比任何.sort
實現的時間復雜度更好(但只有當a,b,c和d可序列化時才有效(如本例所示))。
您可以獲取一個Map
和一組分組鍵,並收集每個組的值。
var array = [{ a: 1, b: 1, c: 1, d: 1, value: 1, rank: 1 }, { a: 1, b: 1, c: 1, d: 1, value: 2, rank: 2 }, { a: 1, b: 1, c: 1, d: 1, value: 3, rank: 3 }, { a: 1, b: 1, c: 1, d: 1, value: 4, rank: 4 }, { a: 1, b: 1, c: 1, d: 1, value: 5, rank: 5 }, { a: 1, b: 2, c: 1, d: 1, value: 1, rank: 1 }, { a: 1, b: 2, c: 1, d: 1, value: 2, rank: 2 }, { a: 1, b: 2, c: 1, d: 1, value: 3, rank: 3 }, { a: 1, b: 2, c: 1, d: 1, value: 4, rank: 4 }, { a: 1, b: 2, c: 1, d: 1, value: 5, rank: 5 }], keys = ['a', 'b', 'c', 'd'], result = [], map = new Map; array.forEach(o => { var key = keys.map(k => o[k]).join('|'), temp = map.get(key); if (!temp) { map.set(key, temp = Object.assign(...keys.map(k => ({ [k]: o[k] })), { values: {} })); result.push(temp); } temp.values[o.rank] = { value: o.value }; }); console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
下面是使用Set,Map和const方法構建Values對象的方法。
var inputArray = [ {a: 1, b: 1, c: 1, d: 1, value: 1, rank: 1}, {a: 1, b: 1, c: 1, d: 1, value: 2, rank: 2}, {a: 1, b: 1, c: 1, d: 1, value: 3, rank: 3}, {a: 1, b: 1, c: 1, d: 1, value: 4, rank: 4}, {a: 1, b: 1, c: 1, d: 1, value: 5, rank: 5}, {a: 1, b: 2, c: 1, d: 1, value: 1, rank: 1}, {a: 1, b: 2, c: 1, d: 1, value: 2, rank: 2}, {a: 1, b: 2, c: 1, d: 1, value: 3, rank: 3}, {a: 1, b: 2, c: 1, d: 1, value: 4, rank: 4}, {a: 1, b: 2, c: 1, d: 1, value: 5, rank: 5} ]; const getValueObject = (a,b,c,d, arr) => { let obj = {}; arr.filter(i => ia === a && ib === b && ic ===c && id === d) .forEach(item => obj[item.value] = item.rank); return obj; }; // Get a set based on the key a,b,c,d let newArray = [...new Set(inputArray.map(({a,b,c,d}) => `${a},${b},${c},${d}`))] .map(item => { let [a,b,c,d] = item.split(',').map(i => parseInt(i)); // filter and add return { a: a, b: b, c: c, d: d, values: getValueObject(a,b,c,d, inputArray) }; }); console.log(newArray);
這是另一種選擇,首先按a
, b
, c
和d
分組。 然后映射每個組,轉換value
和rank
。
var inputArray = [{a: 1, b: 1, c: 1, d: 1, value: 1, rank: 1}, {a: 1, b: 1, c: 1, d: 1, value: 2, rank: 2}, {a: 1, b: 1, c: 1, d: 1, value: 3, rank: 3}, {a: 1, b: 1, c: 1, d: 1, value: 4, rank: 4}, {a: 1, b: 1, c: 1, d: 1, value: 5, rank: 5}, {a: 1, b: 2, c: 1, d: 1, value: 1, rank: 1}, {a: 1, b: 2, c: 1, d: 1, value: 2, rank: 2}, {a: 1, b: 2, c: 1, d: 1, value: 3, rank: 3}, {a: 1, b: 2, c: 1, d: 1, value: 4, rank: 4}, {a: 1, b: 2, c: 1, d: 1, value: 5, rank: 5}]; function groupBy(array, callback) { return array.reduce((groups, item, ...args) => { const key = callback(item, ...args), group = groups[key] || (groups[key] = []); group.push(item); return groups; }, {}); }; console.log( Object .values( groupBy(inputArray, ({a, b, c, d}) => [a, b, c, d]) ) .map(group => { const {a, b, c, d} = group[0], values = {}; group.forEach(({value, rank}) => values[rank] = {value}); return {a, b, c, d, values}; }) );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.