javascript - Ta bort dubblettvärden från JS-array
Jag har en mycket enkel JavaScript-array som kanske innehåller dubbletter eller inte.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
Jag behöver ta bort dubletterna och lägga de unika värdena i en ny array.
Jag skulle kunna peka på all kod som jag har provat, men jag tror att det är meningslöst eftersom de inte fungerar. Jag accepterar också jQuery-lösningar.
Liknande fråga:
- Hämta alla icke-unika värden (dvs.: dubbletter/mer än ett förekomst) i en array
Svar #1
Sammanfattning
Använda Set-konstruktören och spread-syntaxen:
uniq = [...new Set(array)];
(Observera att variabeln uniq kommer att vara en array... new Set() gör om den till ett set, men [... ] gör om den till en array igen)
»Smart« men naiv sätt
uniqueArray = a.filter(function(item, pos) {
return a.indexOf(item) == pos;
})
I princip itererar vi över arrayen och för varje element kontrollerar vi om det första läget av detta element i arrayen är lika med det aktuella läget. Självklart är dessa två lägen olika för dubletter.
Genom att använda det tredje ("denna array") parametern i filter-callbacken kan vi undvika en closure av array-variabeln:
uniqueArray = a.filter(function(item, pos, self) {
return self.indexOf(item) == pos;
})
Även om den är kortfattad, är denna algoritm inte särskilt effektiv för stora arrayer (kvadratisk tid).
Hashtabeller till räddning
function uniq(a) {
var seen = {};
return a.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}
Så här gör man vanligtvis. Idén är att placera varje element i en hashtabell och sedan kontrollera dess närvaro omedelbart. Detta ger oss linjär tid, men har åtminstone två nackdelar:
- eftersom hash-nycklar i JavaScript bara kan vara strängar eller symboler, skiljer inte denna kod mellan siffror och "numeriska strängar". Det vill säga,
uniq([1,"1"])kommer bara att returnera[1] - Av samma anledning kommer alla objekt att anses vara lika:
uniq([{foo:1},{foo:2}])kommer endast att returnera[{foo:1}].
Det sagt, om dina arrayer endast innehåller primitiva värden och du inte bryr dig om typer (t.ex. det är alltid siffror), är denna lösning optimal.
Det bästa från två världar
En universell lösning kombinerar båda metoderna: den använder hash-sökningar för primitiva värden och linjär sökning för objekt.
function uniq(a) {
var prims = {"boolean":{}, "number":{}, "string":{}}, objs = [];
return a.filter(function(item) {
var type = typeof item;
if(type in prims)
return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
else
return objs.indexOf(item) >= 0 ? false : objs.push(item);
});
}
sortera | unika
Ett annat alternativ är att sortera arrayen först, och sedan ta bort varje element som är lika med det föregående:
function uniq(a) {
return a.sort().filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
});
}
Återigen, detta fungerar inte med objekt (eftersom alla objekt är lika för sort). Dessutom ändrar vi tyst den ursprungliga arrayen som en bieffekt - inte bra! Men om din indata redan är sorterad, är detta vägen att gå (ta bara bort sort från ovanstående).
Unik genom...
Ibland är det önskvärt att göra en lista unik baserat på något annat kriterium än bara likhet, till exempel för att filtrera bort objekt som är olika men delar någon egenskap. Detta kan göras elegant genom att skicka in en callback. Denna "key"-callback appliceras på varje element, och element med lika "keys" tas bort. Eftersom key förväntas returnera en primitiv, fungerar hashtabellen bra här:
function uniqBy(a, key) {
var seen = {};
return a.filter(function(item) {
var k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
})
}
En särskilt användbar key() är JSON.stringify som kommer att ta bort objekt som är fysiskt olika, men som "ser" likadana ut:
a = [[1,2,3], [4,5,6], [1,2,3]]
b = uniqBy(a, JSON.stringify)
console.log(b) // [[1,2,3], [4,5,6]]
Om key inte är primitiv måste du använda linjärsökning:
function uniqBy(a, key) {
var index = [];
return a.filter(function (item) {
var k = key(item);
return index.indexOf(k) >= 0 ? false : index.push(k);
});
}
I ES6 kan du använda en Set:
function uniqBy(a, key) {
let seen = new Set();
return a.filter(item => {
let k = key(item);
return seen.has(k) ? false : seen.add(k);
});
}
eller en Map:
function uniqBy(a, key) {
return [
...new Map(
a.map(x => [key(x), x])
).values()
]
}
som båda också fungerar med icke-primitiva nycklar.
Först eller sist?
När du tar bort objekt med en nyckel kanske du vill behålla det första av "lika" objekt eller det sista.
Använd Set-varianten ovan för att behålla den första, och Map för att behålla den sista:
function uniqByKeepFirst(a, key) {
let seen = new Set();
return a.filter(item => {
let k = key(item);
return seen.has(k) ? false : seen.add(k);
});
}
function uniqByKeepLast(a, key) {
return [
...new Map(
a.map(x => [key(x), x])
).values()
]
}
//
data = [
{a:1, u:1},
{a:2, u:2},
{a:3, u:3},
{a:4, u:1},
{a:5, u:2},
{a:6, u:3},
];
console.log(uniqByKeepFirst(data, it => it.u))
console.log(uniqByKeepLast(data, it => it.u))Bibliotek
Både underscore och Lo-Dash tillhandahåller uniq-metoder. Deras algoritmer är i princip liknande det första kodexemplet ovan och kan sammanfattas så här:
var result = [];
a.forEach(function(item) {
if(result.indexOf(item) < 0) {
result.push(item);
}
});
Detta är kvadratiskt, men det finns trevliga ytterligare funktioner, som att omsluta inbyggda indexOf, möjligheten att göra unika efter en nyckel (iteratee i deras terminologi), och optimeringar för redan sorterade arrayer.
Om du använder jQuery och inte står ut med något utan en dollar framför det, går det så här:
$.uniqArray = function(a) {
return $.grep(a, function(item, pos) {
return $.inArray(item, a) === pos;
});
}
vilket, återigen, är en variation av den första utdraget.
Prestanda
Funktionsanrop är dyra i JavaScript, därför är de ovanstående lösningarna, så koncisa som de är, inte särskilt effektiva. För maximal prestanda, ersätt filter med en loop och bli av med andra funktionsanrop:
function uniq_fast(a) {
var seen = {};
var out = [];
var len = a.length;
var j = 0;
for(var i = 0; i < len; i++) {
var item = a[i];
if(seen[item] !== 1) {
seen[item] = 1;
out[j++] = item;
}
}
return out;
}
Denna klump fula kod gör samma sak som kodsnutten #3 ovan, men en storleksordning snabbare (från och med 2017 är den bara dubbelt så snabb - JS-kärngänget gör ett fantastiskt jobb!)
function uniq(a) {
var seen = {};
return a.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}
function uniq_fast(a) {
var seen = {};
var out = [];
var len = a.length;
var j = 0;
for(var i = 0; i < len; i++) {
var item = a[i];
if(seen[item] !== 1) {
seen[item] = 1;
out[j++] = item;
}
}
return out;
}
/////
var r = [0,1,2,3,4,5,6,7,8,9],
a = [],
LEN = 1000,
LOOPS = 1000;
while(LEN--)
a = a.concat(r);
var d = new Date();
for(var i = 0; i < LOOPS; i++)
uniq(a);
document.write('<br>uniq, ms/loop: ' + (new Date() - d)/LOOPS)
var d = new Date();
for(var i = 0; i < LOOPS; i++)
uniq_fast(a);
document.write('<br>uniq_fast, ms/loop: ' + (new Date() - d)/LOOPS)ES6
ES6 tillhandahåller Set-objektet, vilket gör saker mycket enklare:
function uniq(a) {
return Array.from(new Set(a));
}
eller
let uniq = a => [...new Set(a)];
Observera att, till skillnad från i Python, itereras ES6-mängder i insättningsordning, så den här koden behåller ordningen på den ursprungliga arrayen.
Men om du behöver en array med unika element, varför inte använda mängder från början?
Generatorer
En "lat", generatorbaserad version av uniq kan byggas på samma grund:
- ta nästa värde från argumentet
- om det redan har setts, hoppa över det
- annars, ge upp det och lägg till det i mängden av redan sedda värden
function* uniqIter(a) {
let seen = new Set();
for (let x of a) {
if (!seen.has(x)) {
seen.add(x);
yield x;
}
}
}
// example:
function* randomsBelow(limit) {
while (1)
yield Math.floor(Math.random() * limit);
}
// note that randomsBelow is endless
count = 20;
limit = 30;
for (let r of uniqIter(randomsBelow(limit))) {
console.log(r);
if (--count === 0)
break
}
// exercise for the reader: what happens if we set `limit` less than `count` and whySvar #2
Snabbt och smutsigt med jQuery:
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniqueNames = [];
$.each(names, function(i, el){
if($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
});
Svar #3
Blev trött på att se alla dåliga exempel med for-loopar eller jQuery. Javascript har de perfekta verktygen för detta nuförtiden: sort, map och reduce.
Uniq minska samtidigt som befintlig ordning bevaras
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniq = names.reduce(function(a,b){
if (a.indexOf(b) < 0 ) a.push(b);
return a;
},[]);
console.log(uniq, names) // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]
// one liner
return names.reduce(function(a,b){if(a.indexOf(b)<0)a.push(b);return a;},[]);
Snabbare unik med sortering
Det finns förmodligen snabbare sätt men det här är ganska bra.
var uniq = names.slice() // slice makes copy of array before sorting it
.sort(function(a,b){
return a > b;
})
.reduce(function(a,b){
if (a.slice(-1)[0] !== b) a.push(b); // slice(-1)[0] means last item in array without removing it (like .pop())
return a;
},[]); // this empty array becomes the starting value for a
// one liner
return names.slice().sort(function(a,b){return a > b}).reduce(function(a,b){if (a.slice(-1)[0] !== b) a.push(b);return a;},[]);
Uppdatering 2015: ES6-version:
I ES6 har du Sets och Spread vilket gör det mycket enkelt och effektivt att ta bort alla dubbletter:
var uniq = [ ...new Set(names) ]; // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]
Sortera baserat på förekomst:
Någon frågade om att sortera resultaten baserat på hur många unika namn det finns:
var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']
var uniq = names
.map((name) => {
return {count: 1, name: name}
})
.reduce((a, b) => {
a[b.name] = (a[b.name] || 0) + b.count
return a
}, {})
var sorted = Object.keys(uniq).sort((a, b) => uniq[a] < uniq[b])
console.log(sorted)
Svar #4
En enradersversion som använder array .filter och .indexOf funktionen:
arr = arr.filter(function (value, index, array) {
return array.indexOf(value) === index;
});
ES6-tillvägagångssätt
arr = arr.filter((value, index, array) =>
array.indexOf(value) === index
)
Svar #5
Vanilla JS: Ta bort dubbletter med ett objekt som en Set
Du kan alltid försöka sätta det i ett objekt och sedan iterera genom dess nycklar:
function remove_duplicates(arr) {
var obj = {};
var ret_arr = [];
for (var i = 0; i < arr.length; i++) {
obj[arr[i]] = true;
}
for (var key in obj) {
ret_arr.push(key);
}
return ret_arr;
}
Vanilla JS: Ta bort dubbletter genom att spåra redan sedda värden (ordningssäkert)
Eller, för en ordningssäker version, använd ett objekt för att lagra alla tidigare sedda värden och kontrollera värden mot det innan du lägger till dem i en array.
function remove_duplicates_safe(arr) {
var seen = {};
var ret_arr = [];
for (var i = 0; i < arr.length; i++) {
if (!(arr[i] in seen)) {
ret_arr.push(arr[i]);
seen[arr[i]] = true;
}
}
return ret_arr;
}
ECMAScript 6: Använd den nya datastrukturen Set (ordningssäker)
ECMAScript 6 lägger till den nya Set-datastrukturen, som låter dig lagra värden av vilken typ som helst. Set.values returnerar element i infogningsordning.
function remove_duplicates_es6(arr) {
let s = new Set(arr);
let it = s.values();
return Array.from(it);
}
Exempel på användning:
a = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
b = remove_duplicates(a);
// b:
// ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"]
c = remove_duplicates_safe(a);
// c:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]
d = remove_duplicates_es6(a);
// d:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]
Svar #6
Använd Underscore.js
Det är ett bibliotek med en mängd funktioner för att manipulera arrayer.
Det är slipsen som passar till jQuerys tuxedo och Backbone.js hängslen.
_.uniq
_.uniq(array, [isSorted], [iterator])Alias: unique
Producerar en duplicatfri version av arrayen, med === för att testa objektlikhet. Om du på förhand vet att arrayen är sorterad, kommer passing av true för isSorted att köra en mycket snabbare algoritm. Om du vill beräkna unika objekt baserat på en transformation, skicka en iterator-funktion.
Exempel
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
alert(_.uniq(names, false));
Obs: Lo-Dash (en konkurrent till Underscore) erbjuder också en jämförbar .uniq-implementation.
Svar #7
En rad:
let names = ['Mike','Matt','Nancy','Adam','Jenny','Nancy','Carl', 'Nancy'];
let dup = [...new Set(names)];
console.log(dup);
Svar #8
Du kan helt enkelt göra det i JavaScript, med hjälp av den andra - index - parametern av filter-metoden:
var a = [2,3,4,5,5,4];
a.filter(function(value, index){ return a.indexOf(value) == index });
eller i kortform
a.filter((v,i) => a.indexOf(v) == i)
Svar #9
använd
Array.filter()så här
var actualArr = ['Apple', 'Apple', 'Banana', 'Mango', 'Strawberry', 'Banana'];
console.log('Actual Array: ' + actualArr);
var filteredArr = actualArr.filter(function(item, index) {
if (actualArr.indexOf(item) == index)
return item;
});
console.log('Filtered Array: ' + filteredArr);detta kan göras kortare i ES6 till
actualArr.filter((item,index,self) => self.indexOf(item)==index);
Här är en bra förklaring av Array.filter()
Svar #10
De bästa svaren har en komplexitet på O(n²), men detta kan göras med bara O(n) genom att använda ett objekt som en hash:
function getDistinctArray(arr) {
var dups = {};
return arr.filter(function(el) {
var hash = el.valueOf();
var isDup = dups[hash];
dups[hash] = true;
return !isDup;
});
}
Detta fungerar för strängar, siffror och datum. Om din array innehåller objekt kommer dock inte ovanstående lösning att fungera eftersom när de tvingas till en sträng, kommer de alla att ha värdet "[object Object]" (eller något liknande) och det är inte lämpligt som uppslagsvärde. Du kan få en O(n)-implementation för objekt genom att sätta en flagga på objektet självt:
function getDistinctObjArray(arr) {
var distinctArr = arr.filter(function(el) {
var isDup = el.inArray;
el.inArray = true;
return !isDup;
});
distinctArr.forEach(function(el) {
delete el.inArray;
});
return distinctArr;
}
Redigering 2019: Moderna versioner av JavaScript gör detta till ett mycket enklare problem att lösa. Att använda Set fungerar, oavsett om din array innehåller objekt, strängar, siffror eller någon annan typ.
function getDistinctArray(arr) {
return [...new Set(arr)];
}
Implementeringen är så enkel att det inte längre är motiverat att definiera en funktion.
Svar #11
Det mest koncisa sättet att ta bort dubbletter från en array med hjälp av inbyggda JavaScript-funktioner är att använda en sekvens som nedan:
vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])
det finns inget behov av slice eller indexOf inom reduce-funktionen, som jag har sett i andra exempel! det är dock logiskt att använda det tillsammans med en filterfunktion:
vals.filter(function(v, i, a){ return i == a.indexOf(v) })
Ännu ett ES6(2015)-sätt att göra detta på som redan fungerar i några webbläsare är:
Array.from(new Set(vals))
eller till och med använda spridningsoperatorn:
[...new Set(vals)]
skål!
Svar #12
Den enklaste jag har stött på hittills. I es6.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl", "Mike", "Nancy"]
var noDupe = Array.from(new Set(names))
https://developer.mozilla.org/sv/docs/Web/JavaScript/Reference/Global_Objects/Set
Svar #13
Lösning 1
Array.prototype.unique = function() {
var a = [];
for (i = 0; i < this.length; i++) {
var current = this[i];
if (a.indexOf(current) < 0) a.push(current);
}
return a;
}
Lösning 2 (med Set)
Array.prototype.unique = function() {
return Array.from(new Set(this));
}
Test
var x=[1,2,3,3,2,1];
x.unique() //[1,2,3]
Prestanda
När jag testade båda implementationerna (med och utan Set) för prestanda i Chrome, upptäckte jag att den med Set är mycket mycket snabbare!
Array.prototype.unique1 = function() {
var a = [];
for (i = 0; i < this.length; i++) {
var current = this[i];
if (a.indexOf(current) < 0) a.push(current);
}
return a;
}
Array.prototype.unique2 = function() {
return Array.from(new Set(this));
}
var x=[];
for(var i=0;i<10000;i++){
x.push("x"+i);x.push("x"+(i+1));
}
console.time("unique1");
console.log(x.unique1());
console.timeEnd("unique1");
console.time("unique2");
console.log(x.unique2());
console.timeEnd("unique2");Svar #14
I ECMAScript 6 (även känt som ECMAScript 2015) kan Set användas för att filtrera bort duplicerade värden. Sedan kan det konverteras tillbaka till en array med hjälp av spridningsoperatorn.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"],
unique = [...new Set(names)];
Svar #15
Gå för den här:
var uniqueArray = duplicateArray.filter(function(elem, pos) {
return duplicateArray.indexOf(elem) == pos;
});
Nu innehåller uniqueArray inga dubbletter.
Svar #16
Följande är mer än 80 % snabbare än den jQuery-metod som listas (se tester nedan). Det är ett svar från en liknande fråga för några år sedan. Om jag stöter på personen som ursprungligen föreslog det kommer jag att ge kredit. Rent JS.
var temp = {};
for (var i = 0; i < array.length; i++)
temp[array[i]] = true;
var r = [];
for (var k in temp)
r.push(k);
return r;
Min testfallsjämförelse: http://jsperf.com/remove-duplicate-array-tests
Svar #17
Jag hade gjort en detaljerad jämförelse av borttagning av dubletter på en annan fråga, men efter att ha märkt att detta är den riktiga platsen ville jag bara dela det här också.
Jag tror att detta är det bästa sättet att göra detta
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
reduced = Object.keys(myArray.reduce((p,c) => (p[c] = true,p),{}));
console.log(reduced);OK .. även om den här är O(n) och de andra är O(n^2) var jag nyfiken på att se en jämförelse mellan benchmark för denna reduce/look-up-tabell och filter/indexOf-kombinationen (jag valde Jeetendras mycket fina implementation https://stackoverflow.com/a/37441144/4543207). Jag förbereder en array med 100 000 objekt fylld med slumpmässiga positiva heltal i intervallet 0-9999 och tar bort dubletterna. Jag upprepar testet 10 gånger och genomsnittet av resultaten visar att de inte kommer i närheten av samma prestanda.
- I Firefox v47 reducera & lut : 14,85 ms vs filter & indexOf : 2836 ms
- I Chrome v51 minskas & lut : 23,90 ms vs filter & indexOf : 1066 ms
Nåväl, okej, än så länge så bra. Men låt oss göra det ordentligt den här gången i ES6-stil. Det ser så häftigt ut..! Men just nu är hur det kommer att prestera mot den kraftfulla lut-lösningen ett mysterium för mig. Låt oss först titta på koden och sedan jämföra prestandan.
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
reduced = [...myArray.reduce((p,c) => p.set(c,true),new Map()).keys()];
console.log(reduced);Wow det var kort..! Men hur är det med prestandan..? Det är vackert... Eftersom den tunga vikten av filter/indexOf lyftes bort från våra axlar kan jag nu testa en array med 1 miljon slumpmässiga positiva heltal i intervallet 0..99999 för att få ett genomsnitt från 10 på varandra följande tester. Jag kan säga att det den här gången är en riktig match. Se resultatet själv :)
var ranar = [],
red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 10;
for (var i = 0; i<count; i++){
ranar = (new Array(1000000).fill(true)).map(e => Math.floor(Math.random()*100000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");Vilken skulle du använda..? Vänta lite...! Låt dig inte luras. Karta är vid förskjutning. Titta nu... i alla ovanstående fall fyller vi en array av storlek n med tal i intervallet < n. Jag menar att vi har en array av storlek 100 och fyller den med slumpmässiga tal 0..9, så det finns definitivt dubbletter och "nästan" säkert har varje tal en dubblett. Hur skulle det vara om vi fyllde en array av storlek 100 med slumpmässiga tal 0..9999. Låt oss nu se Karta spela hemma. Denna gång en array med 100K objekt men slumpmässigt talintervall är 0..100M. Vi kommer att göra 100 på varandra följande tester för att få ett genomsnittligt resultat. Okej, låt oss se satsningarna..! <- ingen stavfel
var ranar = [],
red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 100;
for (var i = 0; i<count; i++){
ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*100000000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");Nu är detta den spektakulära comebacken för Map()..! Kanske kan du nu fatta ett bättre beslut när du vill ta bort duplikaten.
Okej, nu är vi alla glada. Men huvudrollen kommer alltid sist med lite applåder. Jag är säker på att några av er undrar vad Set-objektet skulle göra. Eftersom vi nu är öppna för ES6 och vi vet att Map är vinnaren av de tidigare spelen, låt oss jämföra Map med Set som final. En typisk Real Madrid vs Barcelona-match den här gången... eller är det? Låt oss se vem som vinner el classico :)
var ranar = [],
red1 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
red2 = a => Array.from(new Set(a)),
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 100;
for (var i = 0; i<count; i++){
ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*10000000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("map & spread took: " + avg1 + "msec");
console.log("set & A.from took: " + avg2 + "msec");Wow.. mannen..! Tja, oväntat nog blev det inte alls en el clasico. Mer som Barcelona FC mot CA Osasuna :))
Svar #18
Här är ett enkelt svar på frågan.
var names = ["Alex","Tony","James","Suzane", "Marie", "Laurence", "Alex", "Suzane", "Marie", "Marie", "James", "Tony", "Alex"];
var uniqueNames = [];
for(var i in names){
if(uniqueNames.indexOf(names[i]) === -1){
uniqueNames.push(names[i]);
}
}
Svar #19
En enkel men effektiv teknik är att använda filter-metoden i kombination med filter function(value, index){ return this.indexOf(value) == index }.
Kodexempel :
var data = [2,3,4,5,5,4];
var filter = function(value, index){ return this.indexOf(value) == index };
var filteredData = data.filter(filter, data );
document.body.innerHTML = '<pre>' + JSON.stringify(filteredData, null, '\t') + '</pre>';Se även denna Fiddle.
Svar #20
Här är mycket enkel kod att förstå och använda var som helst (även i PhotoshopScript). Kolla in den!
var peoplenames = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl");
peoplenames = unique(peoplenames);
alert(peoplenames);
function unique(array){
var len = array.length;
for(var i = 0; i < len; i++) for(var j = i + 1; j < len; j++)
if(array[j] == array[i]){
array.splice(j,1);
j--;
len--;
}
return array;
}
//*result* peoplenames == ["Mike","Matt","Nancy","Adam","Jenny","Carl"]
