对象数组(JSON)到单个对象(数据框)

时间:2018-12-15 20:07:33

标签: javascript dataframe

在下面的代码中,我将根据JSON响应创建一个“伪”数据帧,以实现类似Python的数据操作。

是否有比下面发布的方法更详细的方法?

基本上,我需要将对象数组放入单个对象中。所有对象都具有相同的结构。

<script>
    //~ request API for data
    function get_data(callback){
        $.ajax({type:"GET", 
                url: "{% url 'explorer_api:list_activities' %}",
                //~ success: function(data){
                    //~ console.log(data[1])},
                success: callback,
                headers: {'X-CSRFToken': '{{ csrf_token }}'},

        });
    }

    //~ get data and process it
    get_data(function(data) {

        //create dataframe
        function create_dataframe() {
            var activities = data;                  
            var df = {
                number: [],
                athlete: [],
                start_date: [],
                name: [],   
                country: [],
                link: [],
                segment_efforts:[],
                distance: [],
                average_speed: [],
            };

            for (i in activities) {
                df.number.push(activities[i].number);
                df.athlete.push(activities[i].athlete);
                df.start_date.push(activities[i].start_date);
                df.name.push(activities[i].name);
                df.country.push(activities[i].country);
                df.link.push(activities[i].link);
                df.segment_efforts.push(activities[i].segment_efforts);
                df.distance.push(activities[i].distance);
                df.average_speed.push(activities[i].average_speed);
            };
            return df;
        };
        df = create_dataframe()
        console.log(df);
    }); 
</script>

4 个答案:

答案 0 :(得分:0)

您可以使用另一个for-in循环遍历对象的属性,而不用写出每一行。

for(i in activities) {
    for(var prop in df) {
        df[prop].push(activities[i][prop]);
    }
}

我还建议使用传统的for循环或.forEach()之类的其他方法来遍历activities,因为for-in是not recommended for arrays

答案 1 :(得分:0)

您可以使用Object.entries遍历对象中的键。示例:

var activities = [{ number: 1, test: 2 }, { number: 2, test: 3 }]

var df = {}

for (var activity of activities) {
  for (var [key, value] of Object.entries(activity)) {
    if (!df[key]) df[key] = []
    df[key].push(value)
  }
}
df // { number: [1,2], test: [2,3] }

答案 2 :(得分:0)

这里有扩大热液反应的种类。您可以通过遍历对象中的键并使用简单的reduce和其中的forEach来设置值,而不是对值进行硬编码,从而使其更具动态性。这是该代码:

const arr = [{id: 0, value: 'foo'},{id: 1, value: 'bar'},{id: 2, value: 'baz'}];

const obj = arr.reduce((initial, value, index) => {
  const keys = Object.keys(value);
  keys.forEach(key => {
    if(!initial[key]) initial[key] = [value[key]];
    else initial[key].push(value[key]);
  });
  return initial;
}, {});

console.log(obj)

就详细程度而言,这并没有太大变化,但我认为这是比您所提出的问题更好,更动态的实现方式。

答案 3 :(得分:0)

这是一种功能性(ES6)方法:

data.reduce((a,c) => { Object.keys(c).map(k => a[k] = a[k] ? [...a[k],c[k]] : [c[k]]); return a; }, {})

尽管与使用JavaScript的命令式方法相比,我不会押注任何性能提升。

[更新]

这是当务之急,它与上述功能“最接近”:

result = { }
for(var e of DATA){
   for(var p in e){
      if(result[p]) { result[p].push(e[p]) } else { result[p] = [e[p]] }
   }
}

您可能已经注意到,我提出的解决方案对数组中的对象没有任何先入之见-就像具有相同的结构一样。这会为检查结果中的属性带来一些开销。

但是,正如我所怀疑的那样,并且在某些情况下已经注意到,从性能的角度来看,JavaScript的功能方面并没有得到真正的阐述。

但是我想看看自己,所以我在这里测试了以上两个片段:https://jsperf.com/ao-to-oa-imp-func/1

对于我来说,结果令人信服:功能代码比我的Chrome浏览器中的命令性代码慢93%,而在Firefox中则慢99%。