根据数组元素的值对其进行分组

时间:2020-10-05 12:57:23

标签: javascript arrays

我有这个对象数组:

[
  { name: 'foo1', speed: 8 },
  { name: 'foo2', speed: 7 },
  { name: 'foo3', speed: 10 },
  { name: 'foo4', speed: 12 },
  { name: 'foo5', speed: 8 },
  { name: 'foo6', speed: 5 }
]

现在,我想基于“ speed”属性将数组元素分组为块。如果当前,下一个和上一个元素的速度小于等于10,则应将这些元素分组在一起。如果发生其他情况,则将创建另一个组,该组将收集具有speed属性> 10的元素。

最后,我想要一个由3个数组组成的数组:

[
  [
    { name: 'foo1', speed: 8 },
    { name: 'foo2', speed: 7 },
    { name: 'foo3', speed: 10 }
  ], [
    { name: 'foo4', speed: 12 }
  ], [
    { name: 'foo5', speed: 8 },
    { name: 'foo6', speed: 5 }
  ]
]

重要的是要保持元素的顺序,只是将它们分组。基本数组的长度可以变化,因此必须动态计算所有内容。我曾尝试使用一些loadash方法,但没有任何真正的解决方案。

2 个答案:

答案 0 :(得分:2)

如果要按阈值分组,应使用>而不是>=

只需减少项目,然后使用异或逻辑检查即可。

const data = [
  { name: 'foo1', speed: 8 },
  { name: 'foo2', speed: 7 },
  { name: 'foo3', speed: 10 },
  { name: 'foo4', speed: 12 },
  { name: 'foo5', speed: 8 },
  { name: 'foo6', speed: 5 }
];

const groupDataByThreshold = ([ head, ...rest ], key, threshold) =>
  rest.reduce((result, item) => {
    const prevGroup = result[result.length - 1],
          prevItem = prevGroup[prevGroup.length - 1],
          prevOver = prevItem[key] > threshold,
          currOver = item[key] > threshold;
    if ((currOver && prevOver) || (!currOver && !prevOver)) {
      prevGroup.push(item);
    } else {
      result.push([ item ]);
    }
    return result;
  }, [ [ head ] ])

const grouped = groupDataByThreshold(data, 'speed', 10);

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

答案 1 :(得分:0)

您可以使用reduce方法执行此操作,方法是在每次迭代中检查最后添加的元素是<= 10,当前元素是> 10还是反向元素,如果是,则添加新数组。

const data = [
  { name: 'foo1', speed: 8 },
  { name: 'foo2', speed: 7 },
  { name: 'foo3', speed: 10 },
  { name: 'foo4', speed: 12 },
  { name: 'foo5', speed: 8 },
  { name: 'foo6', speed: 5 }
]

const result = data.reduce((r, e, i, a) => {
  const last = a[i - 1]

  if (!last || last.speed <= 10 && e.speed > 10 || last.speed > 10 && e.speed <= 10) {
    r.push([e])
  } else {
    r[r.length - 1].push(e)
  }

  return r;
}, []);

console.log(result)