如何在Javascript中从一个二维数组创建一个对象数组?

4
这类似于我的实际问题,但我觉得它能够说明我需要解决的问题,而不会让事情变得复杂。
我需要通过迭代一个二维数组来创建一个对象数组。这个二维数组看起来类似于下面的"sampleArray"。
let sampleArray = [ 
  ["open",2], 
  ["high",3], 
  ["low",5], 
  ["close", 10], 
  ["volume", 20], 
  ["open",20], 
  ["high",30], 
  ["low",50], 
  ["close", 100], 
  ["volume", 21],
  ["open",21], 
  ["high",33], 
  ["low",51], 
  ["close", 1], 
  ["volume", 2],
  ["open",7], 
  ["high",8], 
  ["low",5], 
  ["close", 11], 
  ["volume", 22]
 ];

我正在格式化一组特别丑陋的API数据,并将数据压缩成一个二维数组。现在我需要将这些值放入一个包含5个对象的数组中,其中每个对象的数据属性由具有特定标签的所有值填充。

newObject = [
    {
     data: [2,20,21, ...]
     label: "open"  
    }, 
    {
     data: [3,50, ...]
     label: "high"
    }, 
    {
     data: [etc...]
     label: "low"  
    }, 
    {
     data: [etc...]
     label: "close"  
     }, 
    {
     data: [etc...]
     label: "volume"  
     }
]

我已经尝试了大约3小时来让这个工作,并且感觉自己一直在走弯路,我不断收到一个错误,即newArray [i] [“label”]未定义,我知道为什么会发生这种情况(还没有具有该属性的对象),但我不确定如何在JavaScript中表达这个想法(如果标签对应的对象不存在,请创建它并将匹配的值添加到其值属性中)。

function makeArray(array) {
  let newArray = [];
  for(let i = 0; i <= array.length; i++){
    if(newArray[i]["label"] !== array[i][0]){
      newArray.push({
        "label": array[i][0],
        "value": array[i][1]
      })
    }    
    else{
      newArray.push({
        "value": array[i][1]
      })
    }
  }
return newArray;
}

let test = makeArray(sampleArray);
console.log(test);

很抱歉,这篇文章有点长。我整天都在处理这个可怕的API,感觉自己一直在原地踏步。我更希望得到一个正确方向的指引,而不是直接的答案。我要去睡觉了,希望明天早上能有人给我提供一些看法。谢谢!


2
所以你基本上想通过标签对新对象进行排序?我会只使用reduce。 - Alex Lemesios
3个回答

5
你可以使用 reduce 函数。

let sampleArray = [
  ["open", 2],
  ["high", 3],
  ["low", 5],
  ["close", 10],
  ["volume", 20],
  ["open", 20],
  ["high", 30],
  ["low", 50],
  ["close", 100],
  ["volume", 21],
  ["open", 21],
  ["high", 33],
  ["low", 51],
  ["close", 1],
  ["volume", 2],
  ["open", 7],
  ["high", 8],
  ["low", 5],
  ["close", 11],
  ["volume", 22]
];


let newObject = Object.values(sampleArray.reduce((c, [n, v]) => {
  c[n] = c[n] || {label: n,data: []};
  c[n].data.push(v);
  return c;
}, {}));

console.log(newObject);


哇!多么棒的解决方案啊!非常感谢! 我知道我必须使用一个reducer函数,但我真的很难理解它们到底是做什么的。 通过尝试反向工程您的解决方案,我觉得我终于对reducer函数有了初步的理解。 再次感谢! - David Arias
1
很高兴能帮助@DavidArias - Eddie
基本上 reduce 的作用是将数组汇总成一个对象。使用 Object.values 将对象转换为数组以进行最终输出。如果您有问题,请告诉我。 :) - Eddie

2
使用原生JS:

let sampleArray = [
  ["open", 2],
  ["high", 3],
  ["low", 5],
  ["close", 10],
  ["volume", 20],
  ["open", 20],
  ["high", 30],
  ["low", 50],
  ["close", 100],
  ["volume", 21],
  ["open", 21],
  ["high", 33],
  ["low", 51],
  ["close", 1],
  ["volume", 2],
  ["open", 7],
  ["high", 8],
  ["low", 5],
  ["close", 11],
  ["volume", 22]
];

function transform(sampArr) {
  let obj = {};                                 // A map equivalent to store repeated value
  
  // Loop through each array within array
  sampArr.forEach(function(arr) {
    if (!obj[arr[0]]) {
      obj[arr[0]] = {};                         // Instantiate the map the first time
    }

    if (!obj[arr[0]].data) {
      obj[arr[0]]["data"] = [];                 // First time instantiate the array
    }

    obj[arr[0]].data.push(arr[1]);              // Push the repeated values
  });


  // Create the structure you want
  return Object.keys(obj).map(function(key) {
    return {
      data: obj[key].data,
      label: key
    };
  });
}

console.log(transform(sampleArray));


我仍然在努力理解这个问题,但是目前为止,我已经得到了以下的答案,请在我出错时纠正我。 在forEach函数中,您正在根据标签数量创建对象,如果对象不存在,则为每个对象创建数据数组并将值推入其中。然后,在映射步骤中,您将所有数据对象定位到结果数组中,并传递“label”的值? - David Arias
@DavidArias,没错,就是这么简单。你懂了。 - Abhijit Kar ツ

1

在达到最终值之前,您可以引入一个临时变量,如下所示 -

const tempObject = sampleArray.reduce((acc, arr) => {
  if (acc.hasOwnProperty(arr[0]) {
    return acc[arr[0]].push(arr[1]);
  }
  return { ...acc, { [arr[0]]: [arr[1]] };
}), {});

现在tempObject将是 -
{
  'open': [2, 20, 21, ...],
  'high': [3, 50, ...],
  'low': [etc, ...],
  'close': [etc, ...],
  'volume': [etc, ...]
}

然后您可以像这样迭代上述对象:
const finalData = Object.keys(tempObject).map(key => (
  {
    data: tempObject[key],
    label: key
  }
);

现在,finalData 将成为所需的对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接