【问题标题】:Combine arrays of objects by object index按对象索引组合对象数组
【发布时间】:2021-04-06 00:29:53
【问题描述】:

我正在为每个与提供的键相同的值过滤一个数组。我确定有一个比我更好的人可以将其浓缩为一次性减少方法,但可惜的是 filter map filter map。

所以我向一个数组提交了一个对象,上面写着[{k:v}, {k2:otherv}],并找到所有不是那个的元素,然后返回那些对象键。

下面的代码返回:

  [
    {k: v1},
    {k: v2},
    {k: v3}
  ]
   [
    {k2: v4},
    {k2: v5},
    {k2: v6}
   ]
 ]

显然要正确映射它,就像它看起来一样 [{k:v1, k2:v4}, {k:v2,k2:v5}, {k:v3, k2:v6}]

我尝试了以下几个示例:

How can I merge two object arrays by index in JavaScript?

Combine same-index objects of two arrays

但没有将每个可能的对象键写入其中,我尝试过的方法都不起作用。

const blogkeys = cont
   .filter((k) => k.type === "blogs")
   .map(({ key, content }) => {
    if (key.includes(".")) {
     let objkey = key.substr(key.indexOf(".") + 1, key.length);

     let obj = { [objkey]: content };

     let arrName = key.substr(0, key.indexOf("."));

     let pushedObj = { [arrName]: [{ ...obj }] };

     return pushedObj;
    } else {
     let obj = { [key]: content };
     return obj;
    }
   });

这会创建我们在父数组中寻找的键


  const everyOtherBlog = blogkeys.map((blogkey) => {
   const returned = blogs
    .filter(
     (f) =>
      !JSON.stringify(f).includes(
       JSON.stringify(blogkey).replace("{", "").replace("}", "")
      )
    )
    .map(({ _doc }) => {
     let obj = {};

     Object.keys(_doc)
      .filter((f) => f === Object.keys(blogkey)[0])
      .map((a) => {
       obj = Object.assign(obj, { [a]: _doc[a] });

       return obj;
      });

     return obj[0];
    });

   return returned;
  });

这将返回您看到的数据集。

这是 blogkeys 的样子:

[0] [
[0]   { title: ' stuff' },
[0]   {
[0]     p1: ' stuff '
[0]   }
[0] ]

制成
  {
[0]     _id: '606a4049d4812928986afc10',
[0]     contentId: '60443ced4e233336f8306b5b',
[0]     type: 'blogs',
[0]     key: 'title',
[0]     content: 'stuff'
[0]   },

一个博客看起来像

{
 title: '',
 p1:''
}

这里的每个人都提供了很多很酷的东西,但由于我输入数据的方式而最终对我没有帮助,当我修复时,我意识到我不需要任何花哨的拉链,只是好的旧 object.fromEntries。虽然其中一些非常有趣,但我会留下这个。

任何帮助都会很棒

【问题讨论】:

  • 您能否添加一个具体的输入数组示例和您想要的确切输出值?这很有趣,但我还没有完全理解它。
  • 你可以使用{...obj1, ...obj2}在不知道键的情况下组合两个对象。

标签: javascript arrays


【解决方案1】:

两个数组

您可以使用map 来实现zip,然后再次使用map 来执行您的转换。此解决方案仅适用于两个输入数组 -

const zip = (a, b) =>
  a.map((x, i) => [x, b[i]])

const foo =
  [{a:1},{a:2},{a:3}]
  
const bar = 
  [{b:4},{b:5},{b:6}]
  
const result = 
  zip(foo, bar).map(o => Object.assign({}, ...o))

console.log(JSON.stringify(result))
[{"a":1,"b":4},{"a":2,"b":5},{"a":3,"b":6}]

许多数组,任意大小

上面,如果ab 比另一个长,你会遇到奇怪的输出。我认为更好的方法是使用生成器。它适用于任意数量的任意大小的输入数组 -

const iter = t =>
  t?.[Symbol.iterator]()

function* zip (...its)
{ let r, g = its.map(iter)
  while (true)
  { r = g.map(it => it.next())
    if (r.some(v => v.done)) return
    yield r.map(v => v.value)
  }
}

const foo =
  [{a:1},{a:2},{a:3}]
  
const bar = 
  [{b:4},{b:5},{b:6}]

const qux =
  [{c:7},{c:8}]

const result =
  Array.from(zip(foo, bar, qux), o => Object.assign({}, ...o))

console.log(JSON.stringify(result))

这一次完成压缩和转换,之后不需要map -

[{"a":1,"b":4,"c":7},{"a":2,"b":5,"c":8}]

没有生成器

如果您不喜欢生成器,但仍希望上述解决方案提供的灵活性,我们可以编写一个简单的zip2 -

const zip2 = ([a, ...nexta], [b, ...nextb]) =>
  a == null || b == null
    ? []                                   // empty
    : [ [a, b], ...zip2(nexta, nextb) ]    // recur

然后是变量zip,它接受任意数量的任意大小的数组-

const zip = (t, ...more) =>
  more.length
    ? zip2(t, zip(...more)).map(([a, b]) => [a, ...b]) // flatten
    : t.map(a => [a])                                  // singleton

现在我们可以zip 任意数量的数组 -

const foo =
  [{a:1},{a:2},{a:3}]

const bar =
  [{b:4},{b:5},{b:6}]

const qux =
  [{c:7},{c:8}]

const result =
  zip(foo, bar, qux).map(o => Object.assign({}, ...o))

console.log(JSON.stringify(result))

展开下面的sn-p,在自己的浏览器中验证结果-

const zip2 = ([a, ...nexta], [b, ...nextb]) =>
  a == null || b == null
    ? []
    : [ [a, b], ...zip2(nexta, nextb) ]

const zip = (t, ...more) =>
  more.length
    ? Array.from(zip2(t, zip(...more)), ([a, b]) => [a, ...b])
    : t.map(a => [a])

const foo =
  [{a:1},{a:2},{a:3}]

const bar =
  [{b:4},{b:5},{b:6}]

const qux =
  [{c:7},{c:8}]

const result =
  zip(foo, bar, qux).map(o => Object.assign({}, ...o))

console.log(JSON.stringify(result))
[{"a":1,"b":4,"c":7},{"a":2,"b":5,"c":8}]

【讨论】:

  • ...谢谢你,我想你让我看着那个身体疼痛......但谢谢你。
  • 不确定您的意思。我更新了第一个zip 以使用map 而不是reduce,因为它更有意义。仍然建议使用生成器方法
  • 只是一个玩笑,迭代器看起来很复杂就是全部
  • 我尝试了生成器,但返回的问题是 1 个数组。所以我拆分数组并将其传递给生成器并得到......实际上是``` [ {k:v1},{k:v2},{k:v3}] [ {k2:v4}, {k2: v5}, {k2: v6} ]```
  • 此答案中的每个代码都可以在您的浏览器中运行,并产生所描述的输出。如果您得到不同的结果,那是因为您的输入不匹配。
【解决方案2】:

您也可以尝试使用 ma​​preduce,这只是另一种选择

function merge(...args) {
    // finding highest length Array to not skip missing elements from other arrays
    // for skipping missing elements use "acc.length < ele.length"
    const maxArray = args.reduce((acc, ele) => acc.length > ele.length ? acc : ele);

    //Iterating over highest length array
    return maxArray.map((ele, index) => 

    //merging all the instances in arrays with same index
    args.reduce((acc, group) => Object.assign(acc, group[index]), {})
    );
}

merge([ {k: 'v1'}, {k: 'v2'}, {k: 'v3'} ], [ {k2: 'v4'}, {k2: 'v5'}, {k2: 'v6'} ]);
// [{"k":"v1","k2":"v4"},{"k":"v2","k2":"v5"},{"k":"v3","k2":"v6"}]

merge([ {k: 'v1'}, {k: 'v2'}], [ {k2: 'v4'}, {k2: 'v5'}, {k2: 'v6'} ])
// [{"k":"v1","k2":"v4"},{"k":"v2","k2":"v5"},{"k2":"v6"}]

merge([ {k: 'v1'}, {k: 'v2'}, {k: 'v3'} ], [ {k2: 'v4'}, {k2: 'v5'}])
//[{"k":"v1","k2":"v4"},{"k":"v2","k2":"v5"},{"k":"v3"}]

【讨论】:

    【解决方案3】:

    这是一个使用.reduce() 的相当简单的解决方案,它可以接受任意数量的各种长度的数组。

    const
      foo = [{ a: 1 }, { a: 2 }, { a: 3 }],
      bar = [{ b: 4 }, { b: 5 }, { b: 6 }],
      qux = [{ c: 7 }, { c: 8 }],
    
      zip = (...arrs) =>
        arrs.reduce((a, arr) => {
          arr.forEach((x, i) => Object.assign((a[i] = a[i] || {}), x));
          // or using logical nullish assignment
          // arr.forEach((x, i) => Object.assign((a[i] ??= {}), x));
          return a;
        }, []);
    
      result = zip(foo, bar, qux);
    
    console.log(JSON.stringify(result))
    // [{ a: 1, b: 4, c: 7 }, { a: 2, b: 5, c: 8 }, { a: 3, b: 6 }]

    【讨论】:

    • 什么是 ??= 因为 vscode 不喜欢它
    • 感谢您指出它是Logical nullish assignment (??=) 运算符。我已经编辑了 sn-p 以使用 Logical OR (||) 短路。
    • vscode 接受了 mdn 对 a[i] 的建议? (a[i] = {})
    • 太好了,是的,假设您使用的是节点,v14 支持空值合并 (??) 而 v15 增加了对逻辑空值分配的支持 (??=)
    【解决方案4】:

    我想分享我最终所做的事情,因为它适用于嵌套数组和简单对象数组,并且被格式化为直接从 mongo db 的等待中获取信息,遗憾的是它只是一个过滤器映射。

    博客 obj 是 { 标题:“东西”, p1:“东西” }

    返回的是压缩后的数组。

      const everyOtherBlog = Object.values(blogObj).map((val) => {
       const b = blogs
        .filter((f) => !JSON.stringify(f).includes(val))
        .map(({ _doc }) => {
         const keys = Object.keys(_doc).filter((k) =>
          Object.keys(blogObj).includes(k)
         );
    
         const entryObj = Object.fromEntries(keys.map((k) => [k, _doc[k]]));
    
         return entryObj;
        });
    
       return b[0];
      });
    

    【讨论】:

      猜你喜欢
      • 2019-08-04
      • 2022-10-14
      • 1970-01-01
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2012-03-24
      • 2023-04-05
      相关资源
      最近更新 更多