【问题标题】:How to create an array of objects from a 2d array in Javascript?如何从 Javascript 中的二维数组创建对象数组?
【发布时间】:2018-08-18 19:58:16
【问题描述】:

这类似于我的实际问题,但我觉得说明了我需要解决的问题,而不会使事情复杂化。

我需要通过遍历一个二维数组来创建一个对象数组。 二维数组看起来像下面的“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 中表达这个想法(如果具有该标签的对象尚不存在,请创建它并将匹配的值添加到它的 value 属性中)。

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,感觉现在我只是在原地运行。我更喜欢正确方向的观点,而不是直接的答案。我要去打麻袋,看看是否有人可以在早上为我提供一点观点。谢谢!

【问题讨论】:

  • 所以你基本上想按标签对新对象进行排序?我会使用 reduce

标签: javascript arrays object populate


【解决方案1】:

你可以使用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 函数,但我真的很难理解它们到底做了什么。我觉得通过尝试对您的解决方案进行逆向工程,我终于对减速器功能有了一个粗略的了解。再次感谢!
  • 乐于帮助@DavidArias
  • 基本上reduce 所做的是将数组汇总为一个对象。使用Object.values 将对象转换为数组以进行最终输出。如果您有任何问题,请告诉我。 :)
【解决方案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 函数中,您根据标签的数量创建对象,如果对象不存在,那么您将为每个对象创建数据数组并将值推送给它们。然后在映射步骤中,您将所有数据对象定位到结果数组中,并传入“标签”的值?
  • @DavidArias,是的,就这么简单。你明白了。
【解决方案3】:

你可以在进入最终值之前引入一个临时变量 -

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 将成为所需的对象。

【讨论】:

    猜你喜欢
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 2015-01-07
    • 2019-06-13
    • 2016-12-27
    相关资源
    最近更新 更多