[英]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.