将名称为 "same" 的对象键数组连接到一个数组中
Joining array of objects keys with "same" name into one array
我正在尝试使用与一个数组“相同”的键来连接一组对象。基本上,我所说的“相同键”的意思是这些键仅在数量上有所不同,这无关紧要。例如:
{ names.0.id: "Here" }
{ names.1.id: "Almost" }
{ names.2.id: "There" }
...
我不想将具有以下语法的所有键合并为一个。喜欢:
{ names: ["Here", "Almost", "There"] }
我有一个包含这些数据的数组。
[{
"id": "123"
}, {
"group_name": "Test Group"
}, {
"admin": "Somthing"
}, {
"email_address": "Somthing@here.com"
}, {
"org.id": "4"
}, {
"created_by": "6"
}, {
"updated_by": "6"
}, {
"students.0.id": "Yes"
}, {
"students.1.id": "No"
}, {
"names.0.id": "Here"
}, {
"names.1.id": "Almost"
}, {
"names.2.id": "There"
}],
[{
"id": "125"
}...
]
...
我想完成的事情:
[{
"id": "123"
}, {
"group_name": "Test Group"
}, {
"admin": "Somthing"
}, {
"email_address": "Somthing@here.com"
}, {
"org.id": "4"
}, {
"created_by": "6"
}, {
"updated_by": "6"
}, {
"students": ["Yes", "No"]
}, {
"names": ["Here", "Almost", "There"]
}]
对于具有以下语法的任何其他键:
name.number.id
我总是想用名称的第一部分加入一个数组
我建议将问题分为三个部分:
- 将
{ key: value }
个对象的数组转换为单个嵌套对象
- 展平此类嵌套对象以仅用它们的值替换
{ id: ... }
个对象
- 根据 key-value-pair
翻译回 one-object
1。合并为单个对象
为了构建嵌套对象,我们将每个键分开 "."
。然后我们成对遍历键以创建我们的嵌套层。当键是数字时,我们添加一个数组。请参阅下面的代码段中的 mergeKvp
。
2。扁平化去掉 { id }
为了展平,我们遍历树。每当我们看到一个对象只有 和 id
属性 时,我们将其替换为该对象的 id 值。请参阅下面代码段中的 flattenObj
。
//// UTILS
// Merge a key value pair in to an object splitting by "."
const mergeKvp = (obj, [key, value]) => {
const path = key.split(".");
let target = obj;
for (let i = 0; i < path.length - 1; i += 1) {
const k1 = path[i];
const k2 = path[i + 1];
if (!target[k1]) target[k1] = isNaN(+k2) ? {} : [];
target = target[k1];
}
target[path.at(-1)] = value;
return obj;
}
// Flatten a nested object structure
const flattenObj = obj => {
// Handle arrays
if (Array.isArray(obj)) return obj.map(flattenObj);
// Handle objects
if (Object(obj) === obj) {
// Replace { id: _ } objects with _
if ("id" in obj && Object.keys(obj).length === 1) return obj.id;
// Recurse for other objects
return Object.fromEntries(
Object.entries(obj).map(([k, v]) => [k, flattenObj(v)])
);
}
// Return value for everything else
return obj;
}
//// APP
// Merge KVP objects in to one big object
const base = Object.assign({}, ...getData());
// Create nested structures out of the dot-keys
const tree = Object.entries(base).reduce(mergeKvp, {})
// Flatten the tree
const output = flattenObj(tree);
// Translate back to array of { key: value } objects
console.log(
Object.entries(output).map(([k, v]) => ({ [k]: v }))
);
function getData() { return [{
"id": "123"
}, {
"group_name": "Test Group"
}, {
"admin": "Somthing"
}, {
"email_address": "Somthing@here.com"
}, {
"org.id": "4"
}, {
"created_by": "6"
}, {
"updated_by": "6"
}, {
"students.0.id": "Yes"
}, {
"students.1.id": "No"
}, {
"names.0.id": "Here"
}, {
"names.1.id": "Almost"
}, {
"names.2.id": "There"
}]; };
我正在尝试使用与一个数组“相同”的键来连接一组对象。基本上,我所说的“相同键”的意思是这些键仅在数量上有所不同,这无关紧要。例如:
{ names.0.id: "Here" }
{ names.1.id: "Almost" }
{ names.2.id: "There" }
...
我不想将具有以下语法的所有键合并为一个。喜欢:
{ names: ["Here", "Almost", "There"] }
我有一个包含这些数据的数组。
[{
"id": "123"
}, {
"group_name": "Test Group"
}, {
"admin": "Somthing"
}, {
"email_address": "Somthing@here.com"
}, {
"org.id": "4"
}, {
"created_by": "6"
}, {
"updated_by": "6"
}, {
"students.0.id": "Yes"
}, {
"students.1.id": "No"
}, {
"names.0.id": "Here"
}, {
"names.1.id": "Almost"
}, {
"names.2.id": "There"
}],
[{
"id": "125"
}...
]
...
我想完成的事情:
[{
"id": "123"
}, {
"group_name": "Test Group"
}, {
"admin": "Somthing"
}, {
"email_address": "Somthing@here.com"
}, {
"org.id": "4"
}, {
"created_by": "6"
}, {
"updated_by": "6"
}, {
"students": ["Yes", "No"]
}, {
"names": ["Here", "Almost", "There"]
}]
对于具有以下语法的任何其他键:
name.number.id
我总是想用名称的第一部分加入一个数组
我建议将问题分为三个部分:
- 将
{ key: value }
个对象的数组转换为单个嵌套对象 - 展平此类嵌套对象以仅用它们的值替换
{ id: ... }
个对象 - 根据 key-value-pair 翻译回 one-object
1。合并为单个对象
为了构建嵌套对象,我们将每个键分开 "."
。然后我们成对遍历键以创建我们的嵌套层。当键是数字时,我们添加一个数组。请参阅下面的代码段中的 mergeKvp
。
2。扁平化去掉 { id }
为了展平,我们遍历树。每当我们看到一个对象只有 和 id
属性 时,我们将其替换为该对象的 id 值。请参阅下面代码段中的 flattenObj
。
//// UTILS
// Merge a key value pair in to an object splitting by "."
const mergeKvp = (obj, [key, value]) => {
const path = key.split(".");
let target = obj;
for (let i = 0; i < path.length - 1; i += 1) {
const k1 = path[i];
const k2 = path[i + 1];
if (!target[k1]) target[k1] = isNaN(+k2) ? {} : [];
target = target[k1];
}
target[path.at(-1)] = value;
return obj;
}
// Flatten a nested object structure
const flattenObj = obj => {
// Handle arrays
if (Array.isArray(obj)) return obj.map(flattenObj);
// Handle objects
if (Object(obj) === obj) {
// Replace { id: _ } objects with _
if ("id" in obj && Object.keys(obj).length === 1) return obj.id;
// Recurse for other objects
return Object.fromEntries(
Object.entries(obj).map(([k, v]) => [k, flattenObj(v)])
);
}
// Return value for everything else
return obj;
}
//// APP
// Merge KVP objects in to one big object
const base = Object.assign({}, ...getData());
// Create nested structures out of the dot-keys
const tree = Object.entries(base).reduce(mergeKvp, {})
// Flatten the tree
const output = flattenObj(tree);
// Translate back to array of { key: value } objects
console.log(
Object.entries(output).map(([k, v]) => ({ [k]: v }))
);
function getData() { return [{
"id": "123"
}, {
"group_name": "Test Group"
}, {
"admin": "Somthing"
}, {
"email_address": "Somthing@here.com"
}, {
"org.id": "4"
}, {
"created_by": "6"
}, {
"updated_by": "6"
}, {
"students.0.id": "Yes"
}, {
"students.1.id": "No"
}, {
"names.0.id": "Here"
}, {
"names.1.id": "Almost"
}, {
"names.2.id": "There"
}]; };