#javascript
Допустим есть такой JSON: [{"title":"a","cost":"56"},{"title":"b","cost":"34"},{"title":"a","cost":"233"},{"title":"c","cost":"3434"},{"title":"a","cost":"434"}] Как найти title, который повторяется чаще всего ? Вот мой вариант, но хотелось бы увидеть более правильное решение let arr = JSON.parse('[{"title":"a","cost":"56"},{"title":"b","cost":"34"},{"title":"a","cost":"233"},{"title":"c","cost":"3434"},{"title":"a","cost":"434"}]'); let names = []; for (let i = 0; i < arr.length; i++) { names.push(arr[i].title); } let counts = {}; let res = 0; names.forEach(function(x) { counts[x] = (counts[x] || 0) + 1; if (counts[x] > res) { res += counts[x]; } }); let max = 0; let maxName = ''; for (let key in counts) { if (max < counts[key]) { max = counts[key]; maxName = key; } } console.log(maxName); // a
Ответы
Ответ 1
Нет смысла делать массив из заголовков - достаточно уже имеющегося. Для словаря вместо пустого объекта лучше использовать Object.create(null), чтобы не было проблем с методами в прототипе объекта. Ещё, если результат не превосходит 231, можно использовать ~~ для приведения к инту - в большинстве случаев помогает от той же проблемы при использовании {} (от всего кроме __proto__). Самых частых может быть несколько. Здесь баг: res += counts[x]; - должно быть просто =, а не +=. Хотя это значение дальше вообще почему-то не используется - непонятно, зачем тогда оно считалось. max < counts[key] - здесь могло бы быть counts[key] === res, если бы в прошлом пункте было написано верно. Я бы сделал так если нужен массив: var arr = JSON.parse('[{"title":"a","cost":"56"},{"title":"b","cost":"34"},{"title":"a","cost":"233"},{"title":"c","cost":"3434"},{"title":"a","cost":"434"}]'); var count = Object.create(null), max = 0, cur; for (var x of arr) { if ((cur = count[x.title] = ~~count[x.title] + 1) > max) { max = cur; } } var res = Object.keys(count).filter(x => count[x] === max); console.log(res); и так, если нужен любой максимум: var arr = JSON.parse('[{"title":"a","cost":"56"},{"title":"b","cost":"34"},{"title":"a","cost":"233"},{"title":"c","cost":"3434"},{"title":"a","cost":"434"}]'); var count = Object.create(null), max = 0, cur, res; for (var x of arr) { if ((cur = count[x.title] = ~~count[x.title] + 1) > max) { max = cur; res = x.title; } } console.log(res);Ответ 2
данный пример имеет ряд технических недоработок, которые решаются незначительными правками: ©Самых частых может быть несколько вызов obj.increment('increment') obj.increment('max') obj.increment('min') всё поломает спасибо @Qwertiy за замечание предлагаю его рассматривать в ракурсе стилистического оформления (повторяемый код должен быть в функции) void function () { let obj = { increment(_key) { if (!this[_key]) this[_key] = 0 this[_key]++ }, get min() { return; }, get max() { let key = null let count = 0 Object.keys(this).forEach(_key => { if (count < this[_key]) { count = this[_key] key = _key } }) return { key, count }; }, } Object.keys(obj).forEach(_key => { Object.defineProperty(obj, _key, { enumerable: false }) }) obj.increment('a') obj.increment('a') obj.increment('c') obj.increment('c') obj.increment('c') obj.increment('b') let { key, count } = obj.max var co = co || document.getElementById('co') console.log(`ключ:"${key}" количество повторений:"${count}"`) co.innerHTML = `ключ:"${key}" количество повторений:"${count}"` }()Ответ 3
Как вариант, но ваша реализация читается лучше ... const json = JSON.parse('[{"title":"a","cost":"56"},{"title":"b","cost":"34"},{"title":"a","cost":"233"},{"title":"c","cost":"3434"},{"title":"a","cost":"434"}]'); const titleCounts = json.reduce(( memo, item ) => ({ ...memo, [item.title]: ( memo[item.title] || 0 ) + 1 }), {}); // Считаем сколько раз каждый из `title` встречается const mostFrequent = Object.keys(titleCounts).reduce(( prev, cur ) => titleCounts[prev] > titleCounts[cur] ? prev : cur); // Ищем ключ с наибольшим значением console.log(titleCounts); console.log(mostFrequent);
Комментариев нет:
Отправить комментарий