javascript将对象转换为数组

时间:2017-06-11 19:00:30

标签: javascript arrays csv d3.js javascript-objects

我正在尝试从CSV数据集构建d3.js热图。使用d3.csv导入后,数据如下所示:

[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, columns: Array(11)]

其中每个对象如下:

Object {0: "0.934999642", 1: "0.1031451091", 2: "0.077435557", 3: 
"0.129644215", 4: "0.666245944", 5: "0.133087829", 6: "0.113218775", 7: 
"0.120796943", 8: "0.257501418", 9: "0.840916491", "": "0"}

我一直在尝试按原样使用数据,但是for循环太慢(真实数据集有1300个值),并且尝试嵌套结构不起作用,因为d3的data()函数只能拿一个数组。

像这样:

var row =  svg.selectAll(".rows")
                     .data(data)
                     .enter()
                     .append("rect")
                     [etc]

d3.selectAll(".blocks")//nested data
                     .data(function(d) {//d has no length property, so this line fails
                        return d;
                     })
                     .enter()
                     .append("rect")
                    [etc] 

如何将对象数组转换为数组数组?或者,有没有办法成功使用对象数组?另外,有没有理由说它不是直接来自数组数组中的CSV而不是这个奇怪的对象数组?这些数据是在Python的Pandas中策划和导出的,如果这样做有所不同,我们可以在那里进行调整。

谢谢。

5 个答案:

答案 0 :(得分:5)

使用Array.prototype.map

的功能样式非常简单
let myArray = Object
    .keys(myObj)
    .map(key => myObj[key]);

虽然您可能希望保证按键按顺序显示并排除非数字键。

let myArray = Object
    .keys(myObj)
    .sort((a,b) => +a - +b)
    .filter(key => !isNaN(+key))
    .map(key => myObj[key]);

您可以通过map将其用于将其应用于父数组

let newArray = bigArray
    .map(el => Object
        .keys(el)
        /* ... */
        .map(key => el[key]));

答案 1 :(得分:0)

您可以迭代数组并将每个对象映射到Object值:

var result=array.map(Object.values)

但它与两个循环的速度相同。

答案 2 :(得分:0)

数组数组。使用带有对象迭代和数组赋值的While循环。从技术上讲,两个循环。实际上应该算作一个循环,因为它是嵌套计数的延续。

var objs = [{
  0: "0.934999642",
  1: "0.1031451091",
  2: "0.077435557",
  3: "0.129644215",
  4: "0.666245944",
  5: "0.133087829",
  6: "0.113218775",
  7: "0.120796943",
  8: "0.257501418",
  9: "0.840916491",
  "": "0"
}, {
  0: "0.934999642",
  1: "0.1031451091",
  2: "0.077435557",
  3: "0.129644215",
  4: "0.666245944",
  5: "0.133087829",
  6: "0.113218775",
  7: "0.120796943",
  8: "0.257501418",
  9: "0.840916491",
  "": "0"
}]

var i = objs.length,
  arr = Array.from(new Array(i), x => []);
while (i--) {
  for (let val in objs[i]) {
    var values = objs[i][val];
    arr[i].push([values]);
  }
}
console.log(arr);

答案 3 :(得分:0)

myObj = {prop1:[object,object,...],prop2:''};

将prop1作为数组,使用:

var result = myObj.prop1;

或 result = myObj.prop1.map(function(item){ / item - 您的每个对象,您可以获得任何属性,例如:return {“name”:item。 name,“value”:item [3];}; / return item;});

result = [{name:Alex,value:Cash},..];

答案 4 :(得分:0)

您已经有4个不同的答案,向您展示如何在数组中转换具有多个属性的对象。但是,正如我在my comment中所说,这对我来说似乎是一个XY problem,因为你最终想要的只是创建一个热图。

当然,您可以使用任何提供的答案在内部选择中创建数据数组。但是,有不同的方法可以实现相同的结果。这个答案只是我对你的目标的两分钱,而不是你实际问的是什么。

当你说data()不接受某个对象时,你是对的。事实上,data()只接受三件事:

  1. 数组;
  2. 一个功能;
  3. 没有
  4. 话虽这么说,我们必须以某种方式在多个对象中转换那个巨大的对象,因为每个单独的对象代表一个数据点。

    准备数据阵列

    假设您有以下CSV(8 x 8矩阵值)。在此CSV中,第一行标题只是列号。所有值(从第二行开始)从0到100:

    1, 2, 3, 4, 5, 6, 7, 8
    99, 01, 01, 56, 65, 34, 87, 65
    76, 99, 73, 23, 54, 62, 12, 15
    54, 77, 66, 23, 98, 76, 11, 12
    13, 24, 56, 76, 88, 75, 43, 76
    12, 33, 44, 52, 45, 87, 65, 67
    88, 76, 67, 87, 54, 34, 44, 45
    12, 13, 24, 65, 45, 47, 76, 87
    65, 43, 23, 42, 42, 34, 42, 17
    

    使用此CSV,您可以创建一个数据数组,其中每个对象都包含行号,列号和值。例如,将CSV解析为名为rawData的数组,我们可以填充名为data的最终数据数组,如下所示:

    rawData.forEach(function(d, i) {
        Object.keys(d).forEach(function(e) {
            data.push({
                row: i,
                column: e,
                value: d[e]
            })
        })
    });
    

    因此,您只需要在所选内容中访问d.rowd.columnd.value

    .attr("x", function(d) {
        return xScale(d.column)
    })
    .attr("y", function(d) {
        return xScale(d.row)
    })
    .attr("fill", function(d) {
        return color(d.value)
    })
    

    这是一个非常简单的演示:

    var svg = d3.select("svg");
    var rawData = d3.csvParse(d3.select("#csv").text())
    var color = d3.scaleLinear().domain([0, 100]).range(["maroon", "lawngreen"]);
    var xScale = d3.scaleBand().domain(d3.range(1, 9, 1)).range([20, 180]);
    var yScale = d3.scaleBand().domain(d3.range(1, 9, 1)).range([20, 180]);
    
    var data = [];
    
    rawData.forEach(function(d, i) {
      Object.keys(d).forEach(function(e) {
        data.push({
          row: i,
          column: e,
          value: d[e]
        })
      })
    });
    
    var rects = svg.selectAll(null)
      .data(data)
      .enter()
      .append("rect")
      .attr("width", xScale.bandwidth() - 2)
      .attr("height", yScale.bandwidth() - 2)
      .attr("x", function(d) {
        return xScale(d.column)
      })
      .attr("y", function(d) {
        return xScale(d.row)
      })
      .attr("fill", function(d) {
        return color(d.value)
      })
    pre {
      display: none;
    }
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg width="200" height="200"></svg>
    <pre id="csv">1,2,3,4,5,6,7,8
    99,01,01,56,65,34,87,65
    76,99,73,23,54,62,12,15
    54,77,66,23,98,76,11,12
    13,24,56,76,88,75,43,76
    12,33,44,52,45,87,65,67
    88,76,67,87,54,34,44,45
    12,13,24,65,45,47,76,87
    65,43,23,42,42,34,42,17</pre>

    请注意,在此演示中,我使用<pre>元素来存储数据,因为我无法在Stack片段中使用d3.csv