如何将对象推送到具有相似名称的数组?
How can I push objects to arrays with similar names?
我有一个可以创建重复部分的表格。现在,当提交表单时,表单会吐出一个巨大的对象。我正在开发一个过滤功能,它可以过滤掉重复的部分并将重复的部分组织成数组,以便它与我的 API.
一起使用
例如
// 基础对象
{
question_10: ""
question_10a: ""
question_11_checkbox: false
question_11_checkbox_copy_0: false
question_11_checkbox_copy_1: true
question_11_text: "110 Monroe St"
question_11_text_copy_0: "186 Aspen Road"
question_12_checkbox: false
question_12_checkbox_copy_0: false
question_12_text: "New York"
question_12_text_copy_0: "South Orange"
...
}
//我要的是
{
question_10: ""
question_10a: ""
question_11_checkbox: false
question_11_checkbox_copies: [
{ question_11_checkbox_copy_0: false }
{ question_11_checkbox_copy_1: true }
]
question_11_text: "101 Monroe St"
question_11_text_copies: [
{ question_11_text_copy_0: "186 Aspen Road"}
]
question_12_checkbox: false
question_12_checkbox_copies: [
{ question_12_checkbox_copy_0: false}
]
question_12_text: "New York"
question_12_text_copies: [
{ question_12_text_copy_0: "South Orange"}
]
...
}
到目前为止,我已经能够从原始对象中过滤掉副本并为副本创建数组
// filter out copy keys
const copiesKey = Object.keys(data).filter(key => key.includes('copy'));
const copy = {};
// create arrays for copies
copiesKey.map(copiedQuestion => {
if (!(`${copiedQuestion.slice(0, copiedQuestion.length - 7)}_copies` in copy)) {
copy[`${copiedQuestion.slice(0, copiedQuestion.length - 7)}_copies`] = [];
}
});
我卡住的地方是不清楚如何将对象匹配到适当的数组并将其推送。
例如
question_11_text_copies: [
{ question_11_text_copy_0: "186 Aspen Road" }
]
到目前为止,我已经尝试对 copy_0 对象的最后三个键进行切片,并使用 array.filter 将键与数组名称匹配,但没有按预期工作。
如何将 'copy_n' 个对象匹配到适当的数组并将这些对象推送到数组?
您可以将对象的条目减少到新对象。对于每个键,使用带前瞻性的 RegExp 查找它是否具有基本键(“copy”之前的键)。如果它没有基本密钥,则将其直接添加到累加器中。如果是,将它添加到适当的“副本”数组(如果需要使用逻辑空赋值 ??=
初始化它)(TS playground)。
const fn = obj => Object.entries(obj)
.reduce((acc, [k, v]) => {
const [baseKey] = k.match(/.*(?=_copy_)/) ?? [] // get the key from an item with copy
if(!baseKey) acc[k] = v // if no baseKey add the item to the accumulator
else {
const copiesKey = `${baseKey}_copies`
acc[copiesKey] ??= [] // if no copies key add a new one to the accumulator
acc[copiesKey].push({ [k]: v }) // create an object and push to the current copies key
}
return acc
}, {})
const obj = {"question_10":"","question_10a":"","question_11_checkbox":false,"question_11_checkbox_copy_0":false,"question_11_checkbox_copy_1":true,"question_11_text":"110 Monroe St","question_11_text_copy_0":"186 Aspen Road","question_12_checkbox":false,"question_12_checkbox_copy_0":false,"question_12_text":"New York","question_12_text_copy_0":"South Orange"}
const result = fn(obj)
console.log(result)
这可能有点过时,但使用 for...in
循环结合针对密钥的正则表达式模式匹配可能是最清晰的解决方案。
const data = {
question_10: "",
question_10a: "",
question_11_checkbox: false,
question_11_checkbox_copy_0: false,
question_11_checkbox_copy_1: true,
question_11_text: "110 Monroe St",
question_11_text_copy_0: "186 Aspen Road",
question_12_checkbox: false,
question_12_checkbox_copy_0: false,
question_12_text: "New York",
question_12_text_copy_0: "South Orange",
};
const copy_n = /^(.*)_copy_(\d+)$/;
const result = {};
for (const key in data) {
const value = data[key];
const match = key.match(copy_n);
if (match) {
const copies_key = `${match[1]}_copies`;
const index = parseInt(match[2], 10);
result[copies_key] ||= [];
result[copies_key][index] = { [key]: value };
} else {
result[key] = value;
}
}
console.log(result);
模式 /^(.*)_copy_(\d+)$/
匹配任何以 _copy_
结尾且后跟一位或多位小数的内容。 _copy_
之前的所有内容都放在捕获组 1 中,_copy_
后面的小数部分放在捕获组 2 中。
如果没有匹配项(else 场景)我们只需将值分配给相同的键。
如果匹配(if 场景)我们首先确定集合键(copies_key
)和要使用的索引。然后我们检查 result[copies_key]
是否已经设置(我们检查它是否是一个精确的真实值)。如果不是,我们将其分配给一个空数组。之后我们使用 index
将对象分配给数组中的正确索引。
我有一个可以创建重复部分的表格。现在,当提交表单时,表单会吐出一个巨大的对象。我正在开发一个过滤功能,它可以过滤掉重复的部分并将重复的部分组织成数组,以便它与我的 API.
一起使用例如
// 基础对象
{
question_10: ""
question_10a: ""
question_11_checkbox: false
question_11_checkbox_copy_0: false
question_11_checkbox_copy_1: true
question_11_text: "110 Monroe St"
question_11_text_copy_0: "186 Aspen Road"
question_12_checkbox: false
question_12_checkbox_copy_0: false
question_12_text: "New York"
question_12_text_copy_0: "South Orange"
...
}
//我要的是
{
question_10: ""
question_10a: ""
question_11_checkbox: false
question_11_checkbox_copies: [
{ question_11_checkbox_copy_0: false }
{ question_11_checkbox_copy_1: true }
]
question_11_text: "101 Monroe St"
question_11_text_copies: [
{ question_11_text_copy_0: "186 Aspen Road"}
]
question_12_checkbox: false
question_12_checkbox_copies: [
{ question_12_checkbox_copy_0: false}
]
question_12_text: "New York"
question_12_text_copies: [
{ question_12_text_copy_0: "South Orange"}
]
...
}
到目前为止,我已经能够从原始对象中过滤掉副本并为副本创建数组
// filter out copy keys
const copiesKey = Object.keys(data).filter(key => key.includes('copy'));
const copy = {};
// create arrays for copies
copiesKey.map(copiedQuestion => {
if (!(`${copiedQuestion.slice(0, copiedQuestion.length - 7)}_copies` in copy)) {
copy[`${copiedQuestion.slice(0, copiedQuestion.length - 7)}_copies`] = [];
}
});
我卡住的地方是不清楚如何将对象匹配到适当的数组并将其推送。 例如
question_11_text_copies: [
{ question_11_text_copy_0: "186 Aspen Road" }
]
到目前为止,我已经尝试对 copy_0 对象的最后三个键进行切片,并使用 array.filter 将键与数组名称匹配,但没有按预期工作。
如何将 'copy_n' 个对象匹配到适当的数组并将这些对象推送到数组?
您可以将对象的条目减少到新对象。对于每个键,使用带前瞻性的 RegExp 查找它是否具有基本键(“copy”之前的键)。如果它没有基本密钥,则将其直接添加到累加器中。如果是,将它添加到适当的“副本”数组(如果需要使用逻辑空赋值 ??=
初始化它)(TS playground)。
const fn = obj => Object.entries(obj)
.reduce((acc, [k, v]) => {
const [baseKey] = k.match(/.*(?=_copy_)/) ?? [] // get the key from an item with copy
if(!baseKey) acc[k] = v // if no baseKey add the item to the accumulator
else {
const copiesKey = `${baseKey}_copies`
acc[copiesKey] ??= [] // if no copies key add a new one to the accumulator
acc[copiesKey].push({ [k]: v }) // create an object and push to the current copies key
}
return acc
}, {})
const obj = {"question_10":"","question_10a":"","question_11_checkbox":false,"question_11_checkbox_copy_0":false,"question_11_checkbox_copy_1":true,"question_11_text":"110 Monroe St","question_11_text_copy_0":"186 Aspen Road","question_12_checkbox":false,"question_12_checkbox_copy_0":false,"question_12_text":"New York","question_12_text_copy_0":"South Orange"}
const result = fn(obj)
console.log(result)
这可能有点过时,但使用 for...in
循环结合针对密钥的正则表达式模式匹配可能是最清晰的解决方案。
const data = {
question_10: "",
question_10a: "",
question_11_checkbox: false,
question_11_checkbox_copy_0: false,
question_11_checkbox_copy_1: true,
question_11_text: "110 Monroe St",
question_11_text_copy_0: "186 Aspen Road",
question_12_checkbox: false,
question_12_checkbox_copy_0: false,
question_12_text: "New York",
question_12_text_copy_0: "South Orange",
};
const copy_n = /^(.*)_copy_(\d+)$/;
const result = {};
for (const key in data) {
const value = data[key];
const match = key.match(copy_n);
if (match) {
const copies_key = `${match[1]}_copies`;
const index = parseInt(match[2], 10);
result[copies_key] ||= [];
result[copies_key][index] = { [key]: value };
} else {
result[key] = value;
}
}
console.log(result);
模式 /^(.*)_copy_(\d+)$/
匹配任何以 _copy_
结尾且后跟一位或多位小数的内容。 _copy_
之前的所有内容都放在捕获组 1 中,_copy_
后面的小数部分放在捕获组 2 中。
如果没有匹配项(else 场景)我们只需将值分配给相同的键。
如果匹配(if 场景)我们首先确定集合键(copies_key
)和要使用的索引。然后我们检查 result[copies_key]
是否已经设置(我们检查它是否是一个精确的真实值)。如果不是,我们将其分配给一个空数组。之后我们使用 index
将对象分配给数组中的正确索引。