Я создал массив имен продуктов, которые имеют дубликаты данных. Используя:
listFoodnames.forEach(x => {
counts[x] = (counts[x] || 0) + 1;
});
Я могу подсчитать, сколько раз каждый элемент существует в массиве.
С помощью:
Object.keys(counts).sort((a, b) => counts[b]-counts[a])
Я могу сортировать количество элементов от наибольшего до самого низкого, однако я теряю фактическое количество, которое я хотел бы сохранить.
Как я могу это решить?
$('document').ready(function() {
var listFoodnames = ["Batteries", "Bread", "Milk", "Bread", "Milk", "Milk"]
var counts = {};
listFoodnames.forEach(x => {
counts[x] = (counts[x] || 0) + 1;
});
console.log(counts) //LOGS EACH ITEM AS PROPERTY AND OCCURRENCES AS VALUE
var sortedCounts = Object.keys(counts).sort((a, b) => counts[b]-counts[a])
console.log(sortedCounts) //LOSES VALUES
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
К сожалению, свойства объекта не гарантируются для заказа по спецификации. Вместо этого вы можете попробовать использовать массив объектов.
Также обратите внимание, что reduce
является более подходящим, чем forEach
когда вы комбинируете элементы в массиве в один объект.
const listFoodnames = ["Batteries", "Bread", "Milk", "Bread", "Milk", "Milk"];
const counts =
Object.values(
listFoodnames.reduce((a, foodName) => {
if (!a[foodName]) a[foodName] = { foodName, count: 0 };
a[foodName].count++;
return a;
}, {})
);
counts.sort((a, b) => a.count - b.count);
console.log(counts);
object properties are not guaranteed to be ordered, per the spec.
С ES6 это изменилось.
Вместо
var sortedCounts = Object.keys(counts).sort((a, b) => counts[b] - counts[a]);
использование
var sortedCounts = Object.entries(counts).sort(([keyA, a], [keyB, b]) => b - a);
Затем вы можете сопоставить каждую запись [key, value]
с новым объектом:
console.log(sortedCounts.map(([key, value]) => ({[key]: value})));
Результат будет выглядеть так:
[
{
"Milk": 3
},
{
"Bread": 2
},
{
"Batteries": 1
}
]
Обратите внимание, что невозможно получить что-то вроде
{
"Milk": 3,
"Bread": 2,
"Batteries": 1
}
работать, поскольку свойства объекта не имеют порядка.
Note, that it is impossible to get something like
, с ES6, это не так, сейчас ..
Все, кто ответил, неправильно сказали → dictionaries are not ordered
Это на самом деле не так, ES6 изменил спецификацию и сказал, что словарь заказан. Хотя до того, как порядок ES6 не был указан, большинство браузеров даже заказали заказ. Заказ, кстати, - порядок вставки. Заказ также будет работать при сериализации, например. JSON.parse/JSON.stringify.
Поэтому, используя эти знания, мы можем сделать результат в формате вашего после, отсортированного объекта.
пример ниже.
var listFoodnames = ["Batteries", "Bread", "Milk", "Bread", "Milk", "Milk"]
var counts = {};
listFoodnames.forEach(x => {
counts[x] = (counts[x] || 0) + 1;
});
console.log(counts) //LOGS EACH ITEM AS PROPERTY AND OCCURRENCES AS VALUE
const sortedCount =
Object.entries(counts).sort((a,b) => b[1] - a[1]).
reduce((a,v) => (a[v[0]] = v[1], a), {});
console.log(sortedCount);