сортировать данные JSON и получать лучшие n записей - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть данные JSON о миллионах записей.Я должен сделать простой, но сложный функционал.

Что мне нужно сделать?

Мне нужно собрать топ-10 самых появляющихся предметов из этого json с их количеством.под самым появившимся я имею в виду наибольшее количество элементов в 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);            
        }
    }
}

Мой вопрос.

Я думаю, что мой путь неправильный, есть ли лучший способ справиться с этой ситуацией.и если мой подход в порядке, то, чего мне не хватает в текущем коде.

любая помощь будет очень признательна.

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Я создал одну логику, и она работает.Шаги следующие:

  • Сортировка массива по имени
  • Считать отсортированный массив и подсчитать количество имен, появляющихся непрерывно, исохранить номер счета
  • Сортировать снова по номеру счета

Пример кода прилагается.Пожалуйста, посмотрите на окончательный результат.

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>
0 голосов
/ 21 сентября 2018

Вы можете уменьшить данные до объекта, который содержит счетчик каждого элемента, проиндексированного строковым элементом.Затем, если не существует достаточно большого количества уникальных объектов, вы можете 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...