如何合并特定的 属性 名称并在特定条件下连接它们的值?

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; }

  1. map() 需要将 input 数组 1:1 中的每个值映射到 output 数组中的值。
  2. reduce() 将对数组中的单个项目进行转换。如果 keyCIRMAT 开头,我们需要检查我们的工作对象 newObj 上是否已经有 CIRMAT 属性。如果我们还没有,这是第一个 CIRMATx 属性,我们需要创建一个包含 value 的数组。如果我们已经有一个数组并且只需要 push() 新的 value 到它。如果密钥不是以 CIRMAT 开头,我们只需将 valuekey 添加到我们的工作对象 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; }