2010-08-26 1 views
13

Что представляет собой элегантный способ взять массив javascript, упорядочить по частоте значений, а затем фильтровать для uniques?Сортировка массива Javascript по частоте, а затем повторение фильтра

Так,

["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"]

становится

["oranges, "bananas", "apples"]

ответ

22

вычисления частоты каждого элемента первой.

{ 
    apples: 1, 
    oranges: 4, 
    bananas: 2 
} 

Затем создайте массив из этого частотного объекта, который также удалит дубликаты.

["apples", "oranges", "bananas"] 

Теперь отсортируйте этот массив в порядке убывания с использованием частотной карты, которую мы создали ранее.

function compareFrequency(a, b) { 
    return frequency[b] - frequency[a]; 
} 

array.sort(compareFrequency); 

Вот весь источник (с использованием вновь вводимых Array functions в ECMA 5) и объединения шагов генерации де-дублирования и карты частот,

function sortByFrequency(array) { 
    var frequency = {}; 

    array.forEach(function(value) { frequency[value] = 0; }); 

    var uniques = array.filter(function(value) { 
     return ++frequency[value] == 1; 
    }); 

    return uniques.sort(function(a, b) { 
     return frequency[b] - frequency[a]; 
    }); 
} 

же, как описано выше, используя регулярные итерации массива.

function sortByFrequencyAndRemoveDuplicates(array) { 
    var frequency = {}, value; 

    // compute frequencies of each value 
    for(var i = 0; i < array.length; i++) { 
     value = array[i]; 
     if(value in frequency) { 
      frequency[value]++; 
     } 
     else { 
      frequency[value] = 1; 
     } 
    } 

    // make array from the frequency object to de-duplicate 
    var uniques = []; 
    for(value in frequency) { 
     uniques.push(value); 
    } 

    // sort the uniques array in descending order by frequency 
    function compareFrequency(a, b) { 
     return frequency[b] - frequency[a]; 
    } 

    return uniques.sort(compareFrequency); 
} 
+0

может стоить кэширования array.length вместо проверки на каждой итерации – second

+1

@ секунда - это хорошая оптимизация для больших наборов данных. Возможно, некоторые браузеры уже делают это внутри. – Anurag

+0

Это, наверное, так же изящно, как вы найдете. – palswim

1

Базовая стратегия:

Создание объекта для использования в качестве хэш-таблицы для отслеживания частоты каждого элемента массива должны быть отсортированы.

Создайте новый массив, содержащий элементы, частотные пары.

Сортировка этого массива по частоте в порядке убывания.

Извлечь элементы из этого массива.

Код:

function descendingUniqueSort(toBeSorted) { 
    var hash = new Object(); 
    toBeSorted.forEach(function (element, index, array) { 
          if (hash[element] == undefined) { 
           hash[element] = 1; 
          } 
          else { 
           hash[element] +=1; 
          }}); 
    var itemCounts = new Array(); 
    for (var key in hash) { 
     var itemCount = new Object(); 
     itemCount.key = key; 
     itemCount.count = hash[key]; 
     itemCounts.push(itemCount); 
    } 
    itemCounts.sort(function(a,b) { if(a.count<b.count) return 1; 
     else if (a.count>b.count) return -1; else return 0;}); 

    return itemCounts.map(function(itemCount) { return itemCount.key; }); 
} 
2

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

Однако я думал, что это могло бы быть полезно, поскольку у меня был несколько иной способ вычисления частоты появления, используя тернарный оператор и проверку, если значение было подсчитано еще несколько иначе.

function sortByFrequencyAndFilter(myArray) 
{ 
    var newArray = []; 
    var freq = {}; 

    //Count Frequency of Occurances 
    var i=myArray.length-1; 
    for (var i;i>-1;i--) 
    { 
     var value = myArray[i]; 
     freq[value]==null?freq[value]=1:freq[value]++; 
    } 

    //Create Array of Filtered Values 
    for (var value in freq) 
    { 
     newArray.push(value); 
    } 

    //Define Sort Function and Return Sorted Results 
    function compareFreq(a,b) 
    { 
     return freq[b]-freq[a]; 
    } 

    return newArray.sort(compareFreq); 
} 
+0

Цикл, который я использую, чтобы подсчитывать частоту вхождений, проверяет постоянное значение и проходит через массив в обратном порядке. Это будет работать быстрее и на больших массивах. – John

5

// возвращает наиболее частое наименее частые

Array.prototype.byCount= function(){ 
    var itm, a= [], L= this.length, o= {}; 
    for(var i= 0; i<L; i++){ 
     itm= this[i]; 
     if(!itm) continue; 
     if(o[itm]== undefined) o[itm]= 1; 
     else ++o[itm]; 
    } 
    for(var p in o) a[a.length]= p; 
    return a.sort(function(a, b){ 
     return o[b]-o[a]; 
    }); 
} 

// Тест

var A= ["apples","oranges","oranges","oranges","bananas","bananas","oranges"]; 
A.byCount() 

/* Возвращаемое значение: (Array) апельсины, бананы, яблоки */

+1

Если бы это был конкурс Code Golf, вы бы выиграли! – palswim

+0

Действительно оцените этот. Модифицировал его на диктофон с подсчетами, на которые ссылается dict [term], спасибо человеку. Большая помощь, только то, что мне нужно – twobob

1
var arr = ["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"].sort(); 
var freq = {}; 
for (var s in arr) freq[s] = freq[s] ? freq[s] + 1 : 0; 
arr.sort(function(a, b) { return freq[a] > freq[b] ? -1 : 1; }); 
for (var i = arr.length - 1; i > 0; i--) if (arr[i] == arr[i - 1]) arr.splice(i,1); 
alert(arr.join(",")); 
1

для первого шага, чтобы вычислить

{ 
    oranges: 4, 
    bananas: 2, 
    apples: 1 
} 

вы можете использовать функцию countBy из underscroe.js

var all=["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"]; 
var frequency=_.countBy(all,function(each){return each}); 

так frequency объекта будет содержать частоту всех уникальных значений, и вы можете получить уникальный список просто называя _.uniq(all) и сортировать этот уникальный список по _.sortBy методы подчеркивания и с помощью frequency объекта вы можете использовать

_.sortBy(_.uniq(all),function(frequencyKey){return -frequency[frequencyKey]}); 

-ve знак используется здесь для сортировки списка в порядке убывания с использованием значения частоты согласно вашему требованию.

Вы можете проверить документацию http://underscorejs.org/ для дальнейшей оптимизации вашей собственной трюк :)

0

Для ES6, просто коды с .filter и .sort ниже

> var arr = ["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"]; 
> arr.filter((key, idx) => arr.lastIndexOf(key) === idx).sort((a, b) => a < b ? -1 : 1); 
    ["apples", "bananas", "oranges"] 
Смежные вопросы