代码之家  ›  专栏  ›  技术社区  ›  barciewicz

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

  •  0
  • barciewicz  · 技术社区  · 6 年前

    在下面的代码中,我从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 回复  |  直到 6 年前
        1
  •  0
  •   ZorgoZ    6 年前

    这是一种功能性(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%。

        2
  •  0
  •   Hydrothermal    6 年前

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

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

    我还建议使用传统的for循环或其他方法,如.foreach()来循环 activities ,因为in是 not recommended for arrays .

        3
  •  0
  •   Sam Denty zneak    6 年前

    你可以使用 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] }
    
        4
  •  0
  •   Cory Kleiser    6 年前

    有点扩展到水热的答案。通过迭代对象中的键并使用简单的 reduce 和A 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)

    就言辞而言,这并没有改变多少,但我认为这是一个比您所讨论的更好、更动态的实现。