【问题标题】:Filter one combination from 6 combinations in an array of objects从对象数组中的 6 个组合中过滤一个组合
【发布时间】:2021-12-17 20:17:19
【问题描述】:

所以我有这个对象数组,其中一个项目有 6 个组合,这些组合被构成为对象。

假设我有这个对象的一个​​组合:

{ "1": "ab", "2": "bc", "3": "ac" }

该数组还包含 5 个其他对象,这些对象具有该对象的不同组合。像这样:

{ "1": "ab", "2": "ac", "3": "bc" }
{ "1": "ac", "2": "bc", "3": "ab" }
{ "1": "ac", "2": "ab", "3": "bc" }
{ "1": "bc", "2": "ac", "3": "ab" }
{ "1": "bc", "2": "ab", "3": "ac" }

这样我有大约 1000 个项目,每个项目有 6 个组合在一个数组中,我需要过滤并返回每个项目的 1 个组合。

所以假设这是一个包含两个项目的 12 种不同组合的数组:

[
    { "1": "ab", "2": "bc", "3": "ac" }
    { "1": "ab", "2": "ac", "3": "bc" }
    { "1": "ac", "2": "bc", "3": "ab" }
    { "1": "ac", "2": "ab", "3": "bc" }
    { "1": "bc", "2": "ac", "3": "ab" }
    { "1": "bc", "2": "ab", "3": "ac" }

    { "1": "de", "2": "ef", "3": "df" }
    { "1": "df", "2": "ef", "3": "de" }
    { "1": "de", "2": "df", "3": "ef" }
    { "1": "ef", "2": "df", "3": "de" }
    { "1": "df", "2": "de", "3": "ef" }
    { "1": "ef", "2": "de", "3": "df" }
]

我想过滤该数组并仅返回每个组合的 1 个组合,如下所示:

[
    { "1": "ab", "2": "bc", "3": "ac" }
    { "1": "de", "2": "ef", "3": "df" }
]

请注意,第一个对象中的“ab”可以是完全不同组合的值,例如:

{ "1": "ab", "2": "df", "3": "fe" }

我怎样才能有效地做到这一点并考虑到良好的性能?

【问题讨论】:

  • 值总是字符串吗?
  • 是的。总是字符串。
  • 您的选择标准是什么?数组元素的顺序是否总是正确的
  • 它可以是任何顺序。

标签: javascript arrays filter


【解决方案1】:

如果值始终是字符串,您可以从每个元素的排序 Object.values() 创建一个复合键,然后使用简单的“分组依据”操作,这里使用 reduce() 累加到 Map

我在这里只设置第一个匹配项(仅当地图没有匹配条目时)将返回第一个匹配项,如果您想要最后一个匹配项,只需在每次迭代时设置键。

const input = [
  { 1: 'ab', 2: 'bc', 3: 'ac' },
  { 1: 'ab', 2: 'ac', 3: 'bc' },
  { 1: 'ac', 2: 'bc', 3: 'ab' },
  { 1: 'ac', 2: 'ab', 3: 'bc' },
  { 1: 'bc', 2: 'ac', 3: 'ab' },
  { 1: 'bc', 2: 'ab', 3: 'ac' },

  { 1: 'de', 2: 'ef', 3: 'df' },
  { 1: 'df', 2: 'ef', 3: 'de' },
  { 1: 'de', 2: 'df', 3: 'ef' },
  { 1: 'ef', 2: 'df', 3: 'de' },
  { 1: 'df', 2: 'de', 3: 'ef' },
  { 1: 'ef', 2: 'de', 3: 'df' },
];

const result = [
  ...input
    .reduce((a, o) => {
      const key = Object.values(o)
        .sort((a, b) => a.localeCompare(b))
        .join('_');

      if (!a.has(key)) a.set(key, o);

      return a;
    }, new Map())
    .values(),
];

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

如果您不介意返回最后一个匹配的组合,您可以在 new Map() 调用中将其简化为 map()

const input = [{ 1: 'ab', 2: 'bc', 3: 'ac' }, { 1: 'ab', 2: 'ac', 3: 'bc' }, { 1: 'ac', 2: 'bc', 3: 'ab' }, { 1: 'ac', 2: 'ab', 3: 'bc' }, { 1: 'bc', 2: 'ac', 3: 'ab' }, { 1: 'bc', 2: 'ab', 3: 'ac' }, { 1: 'de', 2: 'ef', 3: 'df' }, { 1: 'df', 2: 'ef', 3: 'de' }, { 1: 'de', 2: 'df', 3: 'ef' }, { 1: 'ef', 2: 'df', 3: 'de' }, { 1: 'df', 2: 'de', 3: 'ef' }, { 1: 'ef', 2: 'de', 3: 'df' },];

const result = [
  ...new Map(
    input.map((o) => [
      Object.values(o)
        .sort((a, b) => a.localeCompare(b))
        .join('_'),
      o,
    ])
  ).values(),
];

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

下面是一个简单示例,说明如何对过滤器返回的结果数组进行排序。它只是一个接受compare function 的函数,对传递的组合对象的Object.values 进行排序,然后从排序后的值数组中重建对象(这里使用Object.fromEntries(),但如果你不介意0 个索引对象,你可以使用Object.assign() 并放弃额外的map(),即return Object.assign({}, Object.values(obj).sort(compare));)

const input = [
  { 1: 'ab', 2: 'bc', 3: 'ac' },
  { 1: 'ab', 2: 'ac', 3: 'bc' },
  { 1: 'ac', 2: 'bc', 3: 'ab' },
  { 1: 'ac', 2: 'ab', 3: 'bc' },
  { 1: 'bc', 2: 'ac', 3: 'ab' },
  { 1: 'bc', 2: 'ab', 3: 'ac' },

  { 1: 'de', 2: 'ef', 3: 'dc' },
  { 1: 'dc', 2: 'ef', 3: 'de' },
  { 1: 'de', 2: 'dc', 3: 'ef' },
  { 1: 'ef', 2: 'dc', 3: 'de' },
  { 1: 'dc', 2: 'de', 3: 'ef' },
  { 1: 'ef', 2: 'de', 3: 'dc' },
];

const result = [...new Map(input.map((o) => [Object.values(o).sort((a, b) => a.localeCompare(b)).join('_'), o,])).values(),];
console.log('Initial result: ', result);

function sort_combination(obj, compare = (a, b) => a.localeCompare(b)) {
  return Object.fromEntries(
    Object.values(obj)
      .sort(compare)
      .map((v, i) => [i + 1, v])
  );
}

const includes_c = (a, b) => b.includes('c') - a.includes('c') || a.localeCompare(b);

const sorted = result.map((o) => sort_combination(o, includes_c));

console.log('Sorted result: ', sorted);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 嘿伙计。很抱歉打扰您,但如果我想要不同的顺序怎么办?
  • 你建议如何表明你想要什么顺序?
  • 不,我的意思是在第一个 sn-p 中它的 ab bc ac 但是如果我想要 bc ac ab 或 ac bc ab 怎么办?
  • 我明白了,但是你想如何在代码中表明这一点?你会通过所需的订单吗?一旦你有了缩减的数组,你可以根据你的选择对属性进行排序,不需要从过滤器中返回一个特定的。
  • 嗯,假设我在所有组合中有一个共同点。假设 c 在数组所有项的每个组合中。我希望包含 c 的组合位于第一对。像 ac ab bc 或 ec df dc。抱歉,我没有在 OP 中提及这一点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-23
  • 1970-01-01
  • 1970-01-01
  • 2023-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多