如何将对象的值转换为数组?

How do I turn the values from an object into an array?

我有一个轮询温度数据的函数:

{"a":"43",
"b":"43",
"c":"42",
"d":"43",
"e":"40",
"f":"41",
"g":"100",
"h":"42.6"}

我希望能够绘制随时间变化的数据图表,但我想不出将上述数据映射到类似以下数据的最佳方法:

temps: [{
    name: "a",
    data: ["43","42","43"]
  },
    name: "b",
    data: ["43","42","43"]
  },
    etc...
  ]

我试过下面的代码,并试图弄清楚 javascript 映射函数,但我一直 运行 进入范围问题,其中 "this" 与它在父级中:

this.temp_names.forEach(function(e){
    if(typeof this.temps[e] == "undefined") {
      this.temps[e] = []
    }
    this.temps.e.unshift(this.sys_telemetry.S.temps)
    if (this.temps.e.length > 10) {
      this.temps.e.pop()
    }
})

其中 "temp_names" 是一个键数组。

我在 VueJS 中执行此操作,因此 "this" 正在访问我的组件中的数据。

使用 Array#from, Object#entries, Array#map and destructuring 你可以做这样的事情。

const data={"a":"43","b":"43","c":"42","d":"43","e":"40","f":"41","g":"100","h":"42.6"}

const res = Object.entries(data)
.map(([name, data])=>({name, data:[data]}));

console.log(res);

替代使用 Array#reduce, Map

const data={"a":"43","b":"43","c":"42","d":"43","e":"40","f":"41","g":"100","h":"42.6"}

const res = Array.from(Object
.entries(data)
.reduce((a,[k,v])=>{
  if(!a.has(k)) a.set(k, []);
  a.get(k).push(v);
  return a;
}, new Map()))
.map(([name, data])=>({name, data}));

console.log(res);

graph that data over time

因为您想随着时间的推移执行此操作,所以创建一个数组然后使用 Object.entries、& Array.find 更新结果是有意义的。

这是一个例子。

const values1 = 
  {"a":"43", "b":"43", "c":"42", "d":"43", "e":"40", "f":"41",
  "g":"100", "h":"42.6"};
  
const values2 = 
  {"c":"44", "e":"39"};
  

const results =  [];

function addData(data) {
  Object.entries(data).forEach(([k, v]) => {
    let find = results.find(f => f.name === k);
    if (!find) {
      find = {
        name: k,
        data: []
      }
      results.push(find);
    }
    find.data.push(v);
  });
}

addData(values1); //data packet one arrives
addData(values2); //data packet two arrives
  
console.log(results); //results contains both data packet one & two.

您也许可以使用更简单的数据结构,例如。 { a: [43, 42, 43], b: [1, 2, 3] }

即。您可以使用 name 作为键,使用 data 数组作为值,而不是使用单独的 namedata 键。

如果这可以代表每个密钥的时间线,并且您的初始数据的结构类似于,例如。 [{ a: 43, b: 1, c: 3 }, { a: 42, b: 2, c: 3 }],那么这样的东西可能适合将后者转换为前者:

const output = {};

temp_data.forEach(x => {
  for (const key in x) {
    const y = x[key];

    if (typeof output[key] === 'undefined') {
      output[key] = [];
    }

    output[key].push(y);
  }
});

这会生成一个对象,其键与数据点中的键匹配(例如 "a"、"b"、"c" 等),其值是所有元素的数组每个键的值,可能适合绘制时间线。

(顺便说一句,如果您想将这些值绘制成图表,最好将这些值视为数字 - 例如 1, 2, 3 - 而不是字符串 - 例如 "1", "2", "3" ).

可能有更优雅、更函数式的方法来做到这一点,但这可能会成功!

在我看来,您希望能够向数据对象添加多个数据集。一种方法是让数据对象具有知道如何向自身添加数据等操作的方法,可能如下所示。您可能希望将 index 属性 保持私有,并可能对其进行排序,以便它始终按特定顺序排列,而不管值的添加顺序如何。

var data0 = {"a":"43",
"b":"43",
"c":"42",
"d":"43"};

var data1 = {"a":"53",
"b":"53",
"c":"52",
"d":"53",
"e":"65"
};

class DataObject {

  constructor (data) {
    this.index = [];
    this.data = [];
    if (data) {
      this.addData(data);
    }
  }

  addData (data) {
    Object.keys(data).forEach(key => {
      let idx = this.index.indexOf(key);
      if (idx == -1) {
        idx = this.index.push(key) - 1;
        this.data.push({name:key, data:[]});
      }
      this.data[idx].data.push(data[key]);
    });
  }
}

// Initialise object with some data
let myData = new DataObject(data0);
console.log(JSON.stringify(myData.data));

// Add more data
myData.addData(data1);
console.log(JSON.stringify(myData.data));