簡體   English   中英

從陣列中獲取唯一值的最快方法?

[英]Fastest way to get ONLY unique values from array?

我有這樣的數組

students = [{name: 'Abbey', age: 25}, {name: 'Brian', age: 45},
            {name: 'Colin', age: 25}, {name: 'Dan', age: 78}]

我想要輸出;

uniqueAges = [45, 78]

要明確的是,如果學生數組中出現多次出現的年齡值,我不希望在uniqueAges數組中有任何具有該年齡的對象。 'Abbey'和'Colin'的年齡相同,所以他們出去了。

我知道我可以做這樣的事情並運行uniqueAgeGetter(students)

   function uniqueAgeGetter(list){
   var listCopy = list.slice();
   var uniqueAges = list.slice();
   for (var i = list.length - 1; i >= 0; i--) {
        for (var j = listCopy.length - 1; j >= 0; j--) {
            if(listCopy[j].name !== list[i].name && 
                listCopy[j].age == list[i].age){
                  uniqueAges.splice(i, 1)
                }   
            }
    }
   console.log(uniqueAges)
   return uniqueAges
 }

但是沒有第二個循環可以做到嗎? 我不是時間復雜度的專家,但我試圖找到這個任務是否可能是O(n)。

編輯:我不是在詢問是否可以重寫uniqueAgeGetter以更好地閱讀或使用map,reduce或filter等功能(因為我的理解是它們最終也是一個循環)。

我的問題是,uniqueAgeGetter能否以減少時間復雜度的方式進行重構? 只用一個循環就可以完成嗎?

謝謝。

這可以在O(n)時間內通過計算年齡被看到的次數來完成,並且用多於一的計數來過濾年齡。

由於年齡有合理的限制,我們可以使用長度等於最大可能年齡的整數數組來存儲年齡計數。 在下面的示例中,我將最大可能年齡設為200

 var students = [ {name: 'Abbey', age: 25 }, {name: 'Brian', age: 45 }, {name: 'Colin', age: 25 }, {name: 'Dan', age: 78 } ]; var studentAges = students.map(val => val.age); var ageCounts = Array(200).fill(0); studentAges.forEach(age => ageCounts[age] += 1); var uniqueAges = studentAges.filter(age => ageCounts[age] == 1); console.log(uniqueAges); 

你可以使用reduce

第一個reduce是總結數組並使用age作為鍵將其轉換為對象。 使用年齡作為關鍵將更容易檢查年齡是否已經存在。 對象屬性將具有類似[2,true]的數組值,其中第一個元素是年齡,第二個元素告訴年齡是否有重復。 使用Object.values會將對象轉換為數組。

第二個reduce是形成所需的輸出。

 let students = [{name: 'Abbey', age: 25 }, {name: 'Brian', age: 45 },{name: 'Colin', age: 25 }, {name: 'Dan', age: 78 }]; let uniqueAges = Object.values(students.reduce((c, v) => { if (c[v.age] === undefined) c[v.age] = [v.age, true]; else c[v.age][1] = false; return c; }, {})).reduce((c, v) => { if (v[1]) c.push(v[0]); return c; }, []); console.log(uniqueAges); 

  • 第一個想法,我們可以做兩步:

    第1步:對數組進行排序

    - 有很多算法可以做到這一點。 據我所知,目前,最佳算法的復雜性現在是O(Nlog(N)),其中N是數組的數量。

    第2步:刪除重復的元素

    - 該步驟的復雜度為O(N)因此,在兩個步驟中,復雜度為O(N)+ O(Nlog(N))。 最后,復雜性是O(Nlog(N))

  • 第二個想法

    這也具有O(Nlog(N))的復雜性,但是下次想要獲得唯一年齡時它將是O(N)。

    您可以使用一些自定義在二進制搜索樹中重建,而不是將數據保存在數組中。 此樹中的此節點將保存具有相同年齡的所有元素。

    第一次構建樹時的復雜性是O(Nlog(N))

關於復雜度為O(N)的算法,目前我認為沒有技術可以解決它。 :d

這是你可以做到的一種方式。 我認為時間復雜度為O(n^2) ,其中n是原始數組中元素的數量, m是輸出數組中唯一元素的數量。

 const students = [ {name: 'Abbey', age: 25 }, {name: 'Brian', age: 45 }, {name: 'Colin', age: 25 }, {name: 'Dan', age: 78 } ]; const uniqueStudents = students.map(val => val.age) .sort() .reduce((current, next) => { return current.length === 0 ? [].concat(current, next) : current[current.length - 1] !== next ? [].concat(current, next) : current.slice(0, -1); }, []); console.log(uniqueStudents); 

您可以先使用map()獲取所有年齡段,然后使用reduce()filter()獲取預期的uniqueAges

 var students = [{name: 'Abbey', age: 25 }, {name: 'Brian', age: 45 }, {name: 'Colin', age: 25 }, {name: 'Dan', age: 78 }] var uniqueAges = students .map(s => s.age) .reduce(function(acc, item, index, arr){ var ageOccurrences = arr.filter(i => i == item); if(ageOccurrences.length === 1) acc.push(item) return acc; },[]); console.log(uniqueAges); 

🚀單次迭代的最快方法。

 const students = [ {name: `Abbey`, age: 25}, {name: `Brian`, age: 45}, {name: `Colin`, age: 25}, {name: `Dan`, age: 78}, {name: `Dan`, age: 25} ] // no global variables function unique(key) { const occurrences = {} const list = {} return (result, next, index, {length}) => { const value = next[key] if (list[value]) { occurrences[value] = value } else { list[value] = value result.push(value) } return index === length - 1 ? result.filter(v => !occurrences[v]) : result } } const uniqueNames = students.reduce(unique(`name`), []) const uniqueAges = students.reduce(unique(`age`), []) console.log(uniqueAges) 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM