【问题标题】:sort JSON data and get top n records对 JSON 数据进行排序并获得前 n 条记录
【发布时间】:2018-09-21 16:30:17
【问题描述】:

我有大约数百万条记录的 json 数据。我必须做一个简单但棘手的功能。

我必须做什么?

我必须从该 json 中收集前 10 个出现次数最多的项目及其计数。大多数出现,我的意思是json中项目的最多计数。我还不确定,我将如何使用计数,我的意思是我可以将它添加到与属性相同的 json 对象中。

这是我到目前为止所做的。

//my origional json, it's too big but adding some portion of it.
var jsonData = [    
  {
    "id": "5",
    "name": "#5"
  },
  {
    "id": "1",
    "name": "#1"
  },
  {
    "id": "2",
    "name": "#2"
  },
  {
    "id": "8",
    "name": "#8"
  },
  {
    "id": "1",
    "name": "#1"
  },
  {
    "id": "10",
    "name": "#10" 
  },  
  {
    "id": "2",
    "name": "#2"
  }];    

var top10Data = [];

//geting top 10 items
function getTop10Data() {
    var i = 0;
    while (i <= 20) {
        top10Data.push(getTop1Data());
        i++;
    }

    return true;
}

//getting top 1 data that has max count in json
function getTop1Data() {
    var store = jsonData, distribution = {}, max = 0, result = [];

    store.forEach(function (a) {
        distribution[a] = (distribution[a] || 0) + 1;
        if (distribution[a] > max) {
            max = distribution[a];
            result = [a];
            return;
        }
        if (distribution[a] === max) {
            result.push(a);
        }
    });

    //remove this item with it's all occurences, and push it to top10Data
    removeData(result); 

    return result;
}

//remove items from origional json. but this is not working properly as it removes only one item from top
function removeData(result) {
    var length = jsonData.length;
    for (var i = 0; i < length; i++) {
        if (jsonData[i].toppings === result[0].toppings) {
            jsonData.splice(jsonData[i], 1);            
        }
    }
}

我的问题。

我觉得我走的路不合适,有没有更好的方法来处理这种情况。如果我的方法没问题,我在当前代码中缺少什么。

任何帮助将不胜感激。

【问题讨论】:

  • 您能否发布您正在处理的实际输入以及所需的输出?
  • 实际输入太大而无法包含。我可以添加其中的一部分。
  • 嘿,你为什么使用函数只是为了创建一个子数组..你可以很容易地使用“array.slice”..
  • 谢谢,你能举一个你想要的输出的例子吗?你想要一个最常见元素的数组,没有重复,还是什么?
  • @PranbirSarkar 好吧,我虽然它会使其易于操作。

标签: javascript jquery sorting optimization


【解决方案1】:

您可以将数据缩减为一个对象,该对象包含每个项目的计数,由字符串化项目索引。然后,如果没有相当多的唯一对象,您可以sort 条目按其出现次数,然后对前 10 个进行切片。

var jsonData = [    
  {
    "id": "5",
    "name": "#5"
  },
  {
    "id": "1",
    "name": "#1"
  },
  {
    "id": "2",
    "name": "#2"
  },
  {
    "id": "8",
    "name": "#8"
  },
  {
    "id": "1",
    "name": "#1"
  },
  {
    "id": "10",
    "name": "#10" 
  },  
  {
    "id": "2",
    "name": "#2"
  }];
 const counts = jsonData.reduce((a, obj) => {
  const string = JSON.stringify(obj);
  a[string] = (a[string] || 0) + 1
  return a;
}, {});
const result = Object.entries(counts)
  .sort((a, b) => b[1] - a[1])
  .slice(0, 10)
  .map(([string, count]) => ({ count, obj: JSON.parse(string) }));
console.log(result);

要将计数添加到原始数据中,请在构造 counts 对象后迭代数据:

var jsonData = [    
  {
    "id": "5",
    "name": "#5"
  },
  {
    "id": "1",
    "name": "#1"
  },
  {
    "id": "2",
    "name": "#2"
  },
  {
    "id": "8",
    "name": "#8"
  },
  {
    "id": "1",
    "name": "#1"
  },
  {
    "id": "10",
    "name": "#10" 
  },  
  {
    "id": "2",
    "name": "#2"
  }];
 const counts = jsonData.reduce((a, obj) => {
  const string = JSON.stringify(obj);
  a[string] = (a[string] || 0) + 1
  return a;
}, {});
jsonData.forEach((item) => {
  item.count = counts[JSON.stringify(item)];
});
console.log(jsonData);

【讨论】:

  • 嘿@certainPerformance,这确实有效。我得到了我的预期。非常感谢。
  • 很酷的解决方案,与我之前做的代码相比,不需要太多时间。
【解决方案2】:

我创建了一个逻辑并且它正在工作。 步骤如下:

  • 根据名称对数组进行排序
  • 读取排序好的数组,统计出现的名字个数 连续存储计数数
  • 根据计数重新排序

附上示例代码。请看最终结果。

var jsonData = [    
  {
    "id": "5",
    "name": "#5"
  },
  {
    "id": "1",
    "name": "#1"
  },
  {
    "id": "2",
    "name": "#2"
  },
  {
    "id": "8",
    "name": "#8"
  },
  {
    "id": "1",
    "name": "#1"
  },
  {
    "id": "10",
    "name": "#10" 
  },  
  {
    "id": "2",
    "name": "#2"
  }];    
   
  
  
  $('#output1').html(JSON.stringify(jsonData));
  
	jsonData.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)
  
  $('#output2').html(JSON.stringify(jsonData));
  
  let newArray= [];
  
  	let total = 1;
for(let i=0;i<jsonData.length;i++){
 let nextName = (i==jsonData.length -1)?0 :	jsonData[i+1].name;
    let currentName = jsonData[i].name;
    
    if(nextName != currentName){
      newArray.push({
      	id : jsonData[i].id,
        name : currentName,
        count : total
      });
				total = 1;
      }
      else{
      	total+=1;
      }
  }
  
  $('#output3').html(JSON.stringify(newArray));
  
  //Lets sort it again based on count and take the top 10
  
newArray.sort((a, b) => a.count > b.count ? -1 : a.count < b.count ? 1 : 0)

newArray = newArray.slice(0, 10); // Here is your Data

$('#output4').html(JSON.stringify(newArray));
  
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p id="output1">

</p>
<p id="output2">

</p>
<p id="output3">

</p>
<p id="output4">

</p>

【讨论】:

    猜你喜欢
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 2013-05-13
    • 1970-01-01
    • 2018-12-12
    相关资源
    最近更新 更多