Подсчитать количество экземпляров строки в очень большом массиве и добавить значение к значению хеша

1

У меня есть очень большой массив слов в массиве, и я хочу рассчитать их все и добавить количество в качестве значения для каждой строки.

Поэтому я, например:

words = ["a", "hello", "hello", "b", "went", "a"]

Я хочу преобразовать это в:

words = [{"a" => 2}, {"b" => 1}, {"hello" => 2}, {"went" => 1}]

Я видел способы просто пересчитать одно слово в строке и вернуть свои вхождения, но как я могу сделать это в больших масштабах, создав массив хэшей с количеством вхождений?

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

Теги:

4 ответа

2
Лучший ответ

В первую очередь вы можете создать объект со значением массива и числом вхождения. Затем пропустите его, чтобы создать массив объектов

var words = ["a", "hello", "hello", "b", "went", "a"];
var rObj = {};
var finalArray = [];
words.map(function(currentValue, index) {
  if (rObj.hasOwnProperty(currentValue)) {
    rObj[currentValue] = rObj[currentValue] + 1;
  } else {
    rObj[currentValue] = 1
  }

});
for (var keys in rObj) {
  var obj = {};
  obj[keys] = rObj[keys];
  finalArray.push(obj)
};
console.log(finalArray)
1

Для действительно огромного массива я предлагаю использовать какое-либо while цикла for и обычную проверку, существует ли ключ со словом. Если не назначить ему нуль. Позже добавьте свойство объекта count.

Наконец, преобразование объекта в массив с требуемой структурой.

var words = ["a", "hello", "hello", "b", "went", "a"],
    w,
    i = words.length,  
    count = Object.create(null),
    result;
    
while (i--) {
    w = words[i];
    if (!count[w]) {
        count[w] = 0;
    }
    count[w]++;
}

result = Object.keys(count).map(function (k) {
    var temp = {};
    temp[k] = count[k];
    return temp;
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
  • 0
    Есть ли способ обойти карту, которая будет оптимизировать по скорости, как назначение? Или я ошибаюсь в этом предположении?
  • 1
    @Arrow, по крайней мере, сначала вам нужно попробовать оба метода, но я думаю, что объект быстрее, потому что он имеет только строки в качестве ключа, тогда как Map может иметь любой тип ключа.
1

Сначала вы можете использовать reduce() для подсчета элементов и возврата объекта, а затем map() для возврата массива значений объекта.

var words = ["a", "hello", "hello", "b", "went", "a"]
var count = words.reduce(function(r, e) {
  if(!r[e]) r[e] = {[e]: 1}
  else r[e][e] += 1
  return r;
}, {})

var result = Object.keys(count).map(e => count[e])
console.log(result)
  • 0
    reduce это хороший выбор. Хотя в зависимости от того, насколько «массивен» массив, вы можете реализовать это с помощью цикла for .
  • 0
    Почему бы вам не поставить (r[e] ? r[e] += 1 : r[e] = 1); return r; внутри слова. words.reduce ? Это спасло бы вызов map . Или я здесь не прав?
Показать ещё 1 комментарий
0

Не считайте повторителей хэшированием. Используйте цикл while для небольших накладных расходов. Задания для расчета. Вы получите ответ на порядок в 5 раз быстрее. Один миллион слов, случайно генерируемых из 12 слов в 1/5 раз.

var wordsArray = ['apple', 'beer', 'cake', 'potato', 'orange', 'monitor', 'program', 'application', 'keyboard', 'javascript', 'gaming', 'network'],
  words = [];
for (i = 0; i < 1000000; i++) {
  words.push(wordsArray[Math.floor(Math.random() * wordsArray.length)]);
}

function getCount(words) {
  var w,
    i = words.length,
    hash = {};
  while (i--) {
    w = words[i];
    if (!hash[w]) {
      hash[w] = 0;
    }
    hash[w]++;
  }
  return hash
}

console.time('Obj-time');
var counts = getCount(words);
array = [];
for (let i in counts) {
  var l = i.length,
    val = counts[i];
  array.push({
    [i]: val * l
  })
}

console.log(array);
console.timeEnd('Obj-time');

Ещё вопросы

Сообщество Overcoder
Наверх
Меню