如何合并特定的 属性 名称并在特定条件下连接它们的值?
How to merge specific property names and concatenate theirs values upon certain conditions?
我有这种类型的数据集:
[
{
CODMAT: '86 ',
LIBMAT: 'Chariot N.50 Damien ',
CODCAR: 'I050DCHE ',
ZONLST: 'A',
ALLLST: 1,
CIRMAT1: 'AUA',
CIRMAT2: 'SUC',
CIRMAT3: 'SAL',
CIRMAT4: 'AU3',
CIRMAT5: ' ',
CIRMAT6: ' '
},
{
...
}
]
我想连接所有“CIRMAT”数据并删除这些为空的数据,如下所示:
{
CODMAT: '86 ',
LIBMAT: 'Chariot N.50 Damien ',
CODCAR: 'I050DCHE ',
ZONLST: 'A',
ALLLST: 1,
CIRMAT: ['AUA','SUC','SAL','AU3']
}
感谢您的帮助
你可以使用Object.entries()
, map()
and reduce()
来达到你想要的效果。
通过使用 trim()
检查 空 字符串,它从字符串中删除前导和尾随空格,然后检查字符串的长度。
const input = [
{
CODMAT: '86 ',
LIBMAT: 'Chariot N.50 Damien ',
CODCAR: 'I050DCHE ',
ZONLST: 'A',
ALLLST: 1,
CIRMAT1: 'AUA',
CIRMAT2: 'SUC',
CIRMAT3: 'SAL',
CIRMAT4: 'AU3',
CIRMAT5: ' ',
CIRMAT6: ' '
},
]
const output = input.map(item => (
Object.entries(item).reduce((newObj, [key, value]) => {
if(key.startsWith("CIRMAT") && typeof value === "string"){
// ignore values that are "empty"
if(value.trim().length === 0) return newObj;
if(!newObj.CIRMAT) newObj.CIRMAT = [value];
else newObj.CIRMAT.push(value);
}
else{
// just assign the same key the same value
newObj[key] = value;
}
return newObj;
}, {})
))
console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }
map()
需要将 input
数组 1:1 中的每个值映射到 output
数组中的值。
reduce()
将对数组中的单个项目进行转换。如果 key
以 CIRMAT
开头,我们需要检查我们的工作对象 newObj
上是否已经有 CIRMAT
属性。如果我们还没有,这是第一个 CIRMATx
属性,我们需要创建一个包含 value
的数组。如果我们已经有一个数组并且只需要 push()
新的 value
到它。如果密钥不是以 CIRMAT
开头,我们只需将 value
和 key
添加到我们的工作对象 newObj
中而不做任何更改。
这应该有效:
const data = [
{
CODMAT: '86 ',
LIBMAT: 'Chariot N.50 Damien ',
CODCAR: 'I050DCHE ',
ZONLST: 'A',
ALLLST: 1,
CIRMAT1: 'AUA',
CIRMAT2: 'SUC',
CIRMAT3: 'SAL',
CIRMAT4: 'AU3',
CIRMAT5: ' ',
CIRMAT6: ' '
},
]
const output = input.map(item => (
Object.entries(item).reduce((formatted, [key, value]) => {
if(key.startsWith("CIRMAT") && typeof value === "string"){
if(value.trim().length === 0) return formatted;
if(!formated.CIRMAT) formatted.CIRMAT = [value];
else formatted.CIRMAT.push(value);
}
else{
formatted[key] = value;
}
return formatted;
}, {})
))
涵盖任何要合并的命名模式的方法 key
/属性 名称通常需要遍历项目的所有条目(key-value 对)将每个 key
分成其 digit-less 规范化 属性 名称及其仅数字后缀(尾随数字)部分。然后它将 merge/collect 只有同时具有新的 key
和要丢弃的 number
的条目,此外 value
不为空(或只是空白序列) .
因此可以使用...
正则表达式... /^(\D+)(\d+)?$/
...匹配 digit-less 前导字符串和 digit-only 尾随字符串的模式,其中两个子字符串都是被俘虏。
Array.prototype.map
以便创建包含 changed/merged 项的新数组。
Object.entries
以获得每个要映射的数组项的 key-value 对。
Array.prototype.reduce
以便处理(合并and/or 收集)要映射的数组项的每个条目。
function mergeEquallyNamedButNumberedEntries(item) {
const regXNumberedKey = /^(\D+)(\d+)?$/;
return Object
.entries(item)
.reduce((merger, [key, value]) => {
const [
match,
mergerKey = null,
trailingNumber = null,
] =
key.match(regXNumberedKey) ?? [];
if (mergerKey !== null) {
if (trailingNumber !== null) {
if (String(value ?? null).trim() !== '') {
(merger[mergerKey] ??= []).push(value);
}
} else {
merger[mergerKey] = value;
}
}
return merger;
}, {});
}
const sampleData = [{
CODMAT: '86 ',
LIBMAT: 'Chariot N.50 Damien ',
CODCAR: 'I050DCHE ',
ZONLST: 'A',
ALLLST: 1,
CIRMAT1: 'AUA',
CIRMAT2: 'SUC',
CIRMAT3: 'SAL',
CIRMAT4: 'AU3',
CIRMAT5: ' ',
CIRMAT6: ' '
}, {
foo: 567,
bar: 'baz',
baz99: ' ',
baz88: ' ',
baz77: '',
biz11: '',
biz22: ' ',
biz33: 'foo',
}];
const result = sampleData
.map(mergeEquallyNamedButNumberedEntries);
console.log({ result, sampleData });
.as-console-wrapper { min-height: 100%!important; top: 0; }
我有这种类型的数据集:
[
{
CODMAT: '86 ',
LIBMAT: 'Chariot N.50 Damien ',
CODCAR: 'I050DCHE ',
ZONLST: 'A',
ALLLST: 1,
CIRMAT1: 'AUA',
CIRMAT2: 'SUC',
CIRMAT3: 'SAL',
CIRMAT4: 'AU3',
CIRMAT5: ' ',
CIRMAT6: ' '
},
{
...
}
]
我想连接所有“CIRMAT”数据并删除这些为空的数据,如下所示:
{
CODMAT: '86 ',
LIBMAT: 'Chariot N.50 Damien ',
CODCAR: 'I050DCHE ',
ZONLST: 'A',
ALLLST: 1,
CIRMAT: ['AUA','SUC','SAL','AU3']
}
感谢您的帮助
你可以使用Object.entries()
, map()
and reduce()
来达到你想要的效果。
通过使用 trim()
检查 空 字符串,它从字符串中删除前导和尾随空格,然后检查字符串的长度。
const input = [
{
CODMAT: '86 ',
LIBMAT: 'Chariot N.50 Damien ',
CODCAR: 'I050DCHE ',
ZONLST: 'A',
ALLLST: 1,
CIRMAT1: 'AUA',
CIRMAT2: 'SUC',
CIRMAT3: 'SAL',
CIRMAT4: 'AU3',
CIRMAT5: ' ',
CIRMAT6: ' '
},
]
const output = input.map(item => (
Object.entries(item).reduce((newObj, [key, value]) => {
if(key.startsWith("CIRMAT") && typeof value === "string"){
// ignore values that are "empty"
if(value.trim().length === 0) return newObj;
if(!newObj.CIRMAT) newObj.CIRMAT = [value];
else newObj.CIRMAT.push(value);
}
else{
// just assign the same key the same value
newObj[key] = value;
}
return newObj;
}, {})
))
console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }
map()
需要将input
数组 1:1 中的每个值映射到output
数组中的值。reduce()
将对数组中的单个项目进行转换。如果key
以CIRMAT
开头,我们需要检查我们的工作对象newObj
上是否已经有CIRMAT
属性。如果我们还没有,这是第一个CIRMATx
属性,我们需要创建一个包含value
的数组。如果我们已经有一个数组并且只需要push()
新的value
到它。如果密钥不是以CIRMAT
开头,我们只需将value
和key
添加到我们的工作对象newObj
中而不做任何更改。
这应该有效:
const data = [
{
CODMAT: '86 ',
LIBMAT: 'Chariot N.50 Damien ',
CODCAR: 'I050DCHE ',
ZONLST: 'A',
ALLLST: 1,
CIRMAT1: 'AUA',
CIRMAT2: 'SUC',
CIRMAT3: 'SAL',
CIRMAT4: 'AU3',
CIRMAT5: ' ',
CIRMAT6: ' '
},
]
const output = input.map(item => (
Object.entries(item).reduce((formatted, [key, value]) => {
if(key.startsWith("CIRMAT") && typeof value === "string"){
if(value.trim().length === 0) return formatted;
if(!formated.CIRMAT) formatted.CIRMAT = [value];
else formatted.CIRMAT.push(value);
}
else{
formatted[key] = value;
}
return formatted;
}, {})
))
涵盖任何要合并的命名模式的方法 key
/属性 名称通常需要遍历项目的所有条目(key-value 对)将每个 key
分成其 digit-less 规范化 属性 名称及其仅数字后缀(尾随数字)部分。然后它将 merge/collect 只有同时具有新的 key
和要丢弃的 number
的条目,此外 value
不为空(或只是空白序列) .
因此可以使用...
正则表达式...
/^(\D+)(\d+)?$/
...匹配 digit-less 前导字符串和 digit-only 尾随字符串的模式,其中两个子字符串都是被俘虏。Array.prototype.map
以便创建包含 changed/merged 项的新数组。Object.entries
以获得每个要映射的数组项的 key-value 对。Array.prototype.reduce
以便处理(合并and/or 收集)要映射的数组项的每个条目。
function mergeEquallyNamedButNumberedEntries(item) {
const regXNumberedKey = /^(\D+)(\d+)?$/;
return Object
.entries(item)
.reduce((merger, [key, value]) => {
const [
match,
mergerKey = null,
trailingNumber = null,
] =
key.match(regXNumberedKey) ?? [];
if (mergerKey !== null) {
if (trailingNumber !== null) {
if (String(value ?? null).trim() !== '') {
(merger[mergerKey] ??= []).push(value);
}
} else {
merger[mergerKey] = value;
}
}
return merger;
}, {});
}
const sampleData = [{
CODMAT: '86 ',
LIBMAT: 'Chariot N.50 Damien ',
CODCAR: 'I050DCHE ',
ZONLST: 'A',
ALLLST: 1,
CIRMAT1: 'AUA',
CIRMAT2: 'SUC',
CIRMAT3: 'SAL',
CIRMAT4: 'AU3',
CIRMAT5: ' ',
CIRMAT6: ' '
}, {
foo: 567,
bar: 'baz',
baz99: ' ',
baz88: ' ',
baz77: '',
biz11: '',
biz22: ' ',
biz33: 'foo',
}];
const result = sampleData
.map(mergeEquallyNamedButNumberedEntries);
console.log({ result, sampleData });
.as-console-wrapper { min-height: 100%!important; top: 0; }