JS按具有两个不同数组和和值的组将数组值分组

时间:2018-08-26 00:39:57

标签: javascript

我有两个数组

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

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

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

我想要输出

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

请帮助填充这2个数组。 用Javascript

2 个答案:

答案 0 :(得分:1)

您可以做的一件事是遍历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

答案 1 :(得分:0)

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]或使用将数组分解为命名值的函数:const foo = ([range, value]) => ...还是不理想。

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

转换为这种格式

如果数据来自您无法控制的系统,则可能无法直接对其进行更改,但仍可以在代码内对其进行转换。这是一个将从Format 3array1创建array2的代码段:

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

更正内部数据类型

此格式仍然存在一件事。我们想对value进行算术运算。但是现在它们被存储为字符串。我们确实应该将它们转换为数字。对该代码段稍作更改即可解决此问题:

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)