繁体   English   中英

JS按具有两个不同数组和总和值的组对数组值进行分组

[英]JS group array values by groups with two different arrays and sum values

我有两个数组

array1 =['0-18''18-19','18-19','18-19','20-22']

每个数组 1 在第二个数组中都有值

array2=['100','200','300','400','500']

我想要输出像

array1 =['0-18''18-19','20-22']
array2=['100','900','500']

请帮助填写这两个数组。 在 JavaScript 中

您可以做的一件事是遍历array1并将元素添加为对象中的键。 对象键是唯一的,因此这将消除重复项。 当您这样做时,您可以从array2添加相应的元素。

 let array1 =['0-18','18-19','18-19','18-19','20-22'] let array2=['100','200','300','400','500'] let sums = array1.reduce((obj, key, index) => { if (!obj.hasOwnProperty(key)) obj[key] = 0 // if we haven't added the key, do it and set it to zero obj[key] += Number(array2[index]) // now add the amount from array2 return obj }, {}) console.log(Object.keys(sums)) // the unique keys will be in the keys of the object console.log(Object.values(sums)) // the sums will be in the values

Mark Meyer 的回答很棒。

不过,我想指出有关您的要求的其他内容。

您的初始数据结构看起来不太理想。 它使用两个单独的数组来保存仅通过共享索引链接的相关数据片段。 我将在下面提出几种替代方案,但首先,我想指出这可能是必需的,因为外部系统为您提供此结构作为输出或要求将其作为输入无济于事。 外部系统可能会决定它们的输入和输出,但您始终可以将其转换为两者之间适合您的任何内容。

更好的格式

由于以下几个原因,共享索引数据格式存在问题:很容易不同步,不那么明确,而且几乎从未真正描述您的潜在问题域。

这些中的任何一个都可能是更好的数据结构:

// Format 1
[
  {"0-18":  "100"},
  {"18-19": "200"},
  {"18-19": "300"},
  {"18-19": "400"},
  {"20-22": "500"}
]

// Format 2
[
  ["0-18",  "100"],
  ["18-19", "200"],
  ["18-19", "300"],
  ["18-19", "400"],
  ["20-22", "500"]
]

// Format 3
[
  {range: "0-18",  value: "100"},
  {range: "18-19", value: "200"},
  {range: "18-19", value: "300"},
  {range: "18-19", value: "400"},
  {range: "20-22", value: "500"}
]

第一种格式仍然很弱。 它确实消除了共享索引问题。 但它并不是那么容易使用。 第二个更容易使用。 但是与它一起工作的代码需要提供数据中缺少的一些信息,即范围是每对的第一个成员,值是第二个,通过像pair[0]pair[1]或 with将数组分解为命名值的const foo = ([range, value]) => ...const foo = ([range, value]) => ...这又是不理想的。

第三种格式是迄今为止最明确的。 它直接链接每个集合中的两条数据,而不依赖于您匹配索引。 它还直接告诉您这两部分代表什么。 这可能不是最好的存储格式,因为它需要更多的空间,但它最容易使用。

转换成这种格式

如果数据来自不受您控制的系统,您可能无法直接更改它,但您仍然可以在代码中对其进行转换。 这是一个片段,它将从array1array2创建Format 3

const data = array1.map((range, idx) => ({range, value: array2[idx]}))

更正内部数据类型

这种格式还有一件事是错误的。 我们想对value s 进行算术运算。 但是现在它们被存储为字符串。 我们真的应该将它们转换为数字。 对该代码段的轻微更改将解决此问题:

const data = array1.map((range, idx) => ({range, value: Number(array2[idx])}))

这会给我们

// Format 4
[
  {range: "0-18",  value: 100},
  {range: "18-19", value: 200},
  {range: "18-19", value: 300},
  {range: "18-19", value: 400},
  {range: "20-22", value: 500}
]

转换这些数据

我们现在可以编写一些类似于 Mark 的代码,但更简单,因为我们从更明确的数据结构开始:

const sums = data.reduce((res, {range, value}) => {
  res[range] = (res[range] || 0) + value
  return res
}, {})

或者,如果我们要在多个地方使用它,我们可以编写一个可重用的函数:

const transform = (data) => data.reduce((res, {range, value}) => {
  res[range] = (res[range] || 0) + value;
  return res
}, {})
// ... later ...
const sums = transform(data)

转换回单独的数组

如果您确实需要两个单独数组中的结果,这就像在 Mark 的回答中一样:

const newArray1 = Object.keys(sums)
const newArray2 = Object.values(sums)

(或者如果您需要将总值重新转换为字符串,您可以这样做

const newArray2 = Object.values(sums).map(String)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM