对象转换协助
Object transformation assistance
我有一个单键值对列表,其中键是一个由 2 部分组成的字符串,描述了应该在 table 上绘制值的位置。这是我第一次就 SO 提出问题,所以请放轻松。
let tiles = [
{ 'A~baz': 'x' },
{ 'A~buzz': 'o' },
{ 'A~fam': '' },
{ 'B~baz': 'x' },
{ 'B~buzz': '' },
{ 'B~fam': '' },
{ 'C~baz': 'x' },
{ 'C~buzz': 'x' },
{ 'C~fam': 'x' }
]
我想把它转换成下面的格式。
[
{ _id: 'A', baz: 'x', buzz: 'o', fam: '' },
{ _id: 'B', baz: 'x', buzz: '', fam: '' },
{ _id: 'C', baz: 'x', buzz: 'x', fam: 'x' }
]
请注意,我需要对数十万个键值对执行此操作。
到目前为止我所做的一切都有效,但我希望可以改进一些地方。
let tiles = [
{ 'C~fam': "x" },
{ 'B~buzz': "" },
{ 'B~fam': "" },
{ 'A~fam': "" },
{ 'A~buzz': "o" },
{ 'B~baz': "x" },
{ 'A~baz': "x" },
{ 'C~baz': "x" },
{ 'C~buzz': "x" },
];
// I thought it would help to sort the array
tiles.sort((a, b) => Object.keys(a)[0].localeCompare(Object.keys(b)[0]));
let obj = {};
tiles.forEach((kvp) => { //kvp = key value pair
let [row,col] = Object.keys(kvp)[0].split('~') //destruct by '~'
let val = Object.values(kvp)[0];
obj[row] = obj[row] ?? {}
obj[row][col] = val;
})
let keys = Object.keys(obj);
let values = Object.values(obj)
let output = [];
for (let i = 0, len = keys.length; i < len; i++) {
output.push(Object.assign({_id : `${keys[i]}`}, values[i]));
}
您通过对数组进行排序将算法的复杂度降为 O(nlog(n))。您无需排序即可解决此问题。由于我们必须遍历所有数组,因此可能的最佳复杂度为 O(n)。假设输入格式始终保持不变,试试这个:
function changeFormat (arr){
const hash = {}
arr.forEach(element => {
const key = Object.keys(element)[0];
const _id = key[0];
if (hash[_id] === undefined)
hash[_id] ={_id, baz:'', buzz:'', fam:''};
const type = key.slice(2);
hash[_id][type] = element[key];
});
return Object.values(hash);
}
这里是单循环解决方案
let res = {};
let arrayRes = [];
tiles.forEach(function(tile) {
let tileKey = Object.keys(tile)[0];
let tileKeySplitted = tileKey.split('~');
let column = tileKeySplitted[0];
let key = tileKeySplitted[1];
if (res[column] == null) {
res[column] = {'_id': column};
arrayRes.push(res[column]);
}
res[column][key] = tile[tileKey];
});
console.log(arrayRes);
您可以将此代码放入一个函数中并重复使用,即使 props 从 baz、buzz、fam 更改,此代码也能正常工作。
let requiredFormat = tiles.reduce((acc, tile) => {
let keys = Object.keys(tile);
let firstKey = keys[0];
let firstKeyArray = firstKey.split("~");
let id = firstKeyArray[0];
let propName = firstKeyArray[1];
let objWithId = acc.find(obj => obj._id === id);
if(objWithId) {
let accumulatorWithoutCurrentObject = acc.filter(obj => obj._id !== id);
let upadtedObjWithId = {...objWithId, [propName]: tile[firstKey]};
let updatedAcc = [
...accumulatorWithoutCurrentObject,
upadtedObjWithId
];
return updatedAcc;
}
let updatedAcc = [
...acc,
{_id: id, [propName]: tile[firstKey]}
];
return updatedAcc;
}, []);
我有一个单键值对列表,其中键是一个由 2 部分组成的字符串,描述了应该在 table 上绘制值的位置。这是我第一次就 SO 提出问题,所以请放轻松。
let tiles = [
{ 'A~baz': 'x' },
{ 'A~buzz': 'o' },
{ 'A~fam': '' },
{ 'B~baz': 'x' },
{ 'B~buzz': '' },
{ 'B~fam': '' },
{ 'C~baz': 'x' },
{ 'C~buzz': 'x' },
{ 'C~fam': 'x' }
]
我想把它转换成下面的格式。
[
{ _id: 'A', baz: 'x', buzz: 'o', fam: '' },
{ _id: 'B', baz: 'x', buzz: '', fam: '' },
{ _id: 'C', baz: 'x', buzz: 'x', fam: 'x' }
]
请注意,我需要对数十万个键值对执行此操作。
到目前为止我所做的一切都有效,但我希望可以改进一些地方。
let tiles = [
{ 'C~fam': "x" },
{ 'B~buzz': "" },
{ 'B~fam': "" },
{ 'A~fam': "" },
{ 'A~buzz': "o" },
{ 'B~baz': "x" },
{ 'A~baz': "x" },
{ 'C~baz': "x" },
{ 'C~buzz': "x" },
];
// I thought it would help to sort the array
tiles.sort((a, b) => Object.keys(a)[0].localeCompare(Object.keys(b)[0]));
let obj = {};
tiles.forEach((kvp) => { //kvp = key value pair
let [row,col] = Object.keys(kvp)[0].split('~') //destruct by '~'
let val = Object.values(kvp)[0];
obj[row] = obj[row] ?? {}
obj[row][col] = val;
})
let keys = Object.keys(obj);
let values = Object.values(obj)
let output = [];
for (let i = 0, len = keys.length; i < len; i++) {
output.push(Object.assign({_id : `${keys[i]}`}, values[i]));
}
您通过对数组进行排序将算法的复杂度降为 O(nlog(n))。您无需排序即可解决此问题。由于我们必须遍历所有数组,因此可能的最佳复杂度为 O(n)。假设输入格式始终保持不变,试试这个:
function changeFormat (arr){
const hash = {}
arr.forEach(element => {
const key = Object.keys(element)[0];
const _id = key[0];
if (hash[_id] === undefined)
hash[_id] ={_id, baz:'', buzz:'', fam:''};
const type = key.slice(2);
hash[_id][type] = element[key];
});
return Object.values(hash);
}
这里是单循环解决方案
let res = {};
let arrayRes = [];
tiles.forEach(function(tile) {
let tileKey = Object.keys(tile)[0];
let tileKeySplitted = tileKey.split('~');
let column = tileKeySplitted[0];
let key = tileKeySplitted[1];
if (res[column] == null) {
res[column] = {'_id': column};
arrayRes.push(res[column]);
}
res[column][key] = tile[tileKey];
});
console.log(arrayRes);
您可以将此代码放入一个函数中并重复使用,即使 props 从 baz、buzz、fam 更改,此代码也能正常工作。
let requiredFormat = tiles.reduce((acc, tile) => {
let keys = Object.keys(tile);
let firstKey = keys[0];
let firstKeyArray = firstKey.split("~");
let id = firstKeyArray[0];
let propName = firstKeyArray[1];
let objWithId = acc.find(obj => obj._id === id);
if(objWithId) {
let accumulatorWithoutCurrentObject = acc.filter(obj => obj._id !== id);
let upadtedObjWithId = {...objWithId, [propName]: tile[firstKey]};
let updatedAcc = [
...accumulatorWithoutCurrentObject,
upadtedObjWithId
];
return updatedAcc;
}
let updatedAcc = [
...acc,
{_id: id, [propName]: tile[firstKey]}
];
return updatedAcc;
}, []);