Mam dwie tablice JavaScript:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
Chcę, aby wynik był:
var array3 = ["Vijendra","Singh","Shakya"];
Tablica wyjściowa powinna mieć powtarzane słowa usunięte.
Jak scalić dwie tablice w JavaScript, aby uzyskać tylko unikalne elementy z każdej tablicy w tej samej kolejności, w jakiej zostały wstawione do oryginalnych tablic?
javascript
arrays
merge
Vijjendra
źródło
źródło
Odpowiedzi:
Aby po prostu scalić tablice (bez usuwania duplikatów)
Zastosowanie wersji ES5
Array.concat
:Wersja ES6 używa destrukcji
Ponieważ nie ma „wbudowanego” sposobu usuwania duplikatów ( ECMA-262 faktycznie ma,
Array.forEach
co byłoby do tego świetne), musimy to zrobić ręcznie:Następnie, aby go użyć:
Pozwoli to również zachować kolejność tablic (tzn. Nie trzeba sortować).
Ponieważ wiele osób denerwuje się powiększaniem prototypów
Array.prototype
ifor in
pętlami, oto mniej inwazyjny sposób ich użycia:Dla tych, którzy mają szczęście pracować z przeglądarkami, w których dostępny jest ES5, możesz użyć
Object.defineProperty
tego w następujący sposób:źródło
[a, b, c]
i[x, b, d]
być tablice (zakładamy, cytaty). concat daje[a, b, c, x, b, d]
. Czy wyjście unikalne () nie byłoby[a, c, x, b, d]
. To nie zachowuje porządku, jak sądzę - wierzę, że OP chce[a, b, c, x, d]
for ... in
zehasOwnProperty
w takim przypadku metoda prototyp jest w porządkuZa pomocą Underscore.js lub Lo-Dash możesz:
http://underscorejs.org/#union
http://lodash.com/docs#union
źródło
underscore.flatten()
, że jest lepszy niż związek, ponieważ wymaga szeregu tablic.Najpierw połącz dwie tablice, następnie odfiltruj tylko unikalne elementy:
Edytować
Zgodnie z sugestią, bardziej rozsądnym rozwiązaniem byłoby odfiltrowanie unikalnych elementów
b
przed połączeniem za
:źródło
a
na dodawanieb
, to czy lepiej będzie zapętlić i użyć wypychania?a.forEach(function(item){ if(a.indexOf(item)<0) a.push(item); });
var c = [...a, ...b.filter(o => !~a.indexOf(o))];
2.var c = [...new Set([...a, ...b])];
☺Jest to rozwiązanie ECMAScript 6 wykorzystujące operator spread i generyczne tablice.
Obecnie działa tylko z przeglądarką Firefox i ewentualnie przeglądarką techniczną przeglądarki Internet Explorer.
Ale jeśli używasz Babel , możesz go mieć teraz.
źródło
Array.from
może być użyty zamiast operatora rozprzestrzeniania:Array.from(new Set([].concat(...arr)))
ES6
LUB
LUB
źródło
union
w ogóle nie ma + Pierwszy przykład wysadza stos w dużeArray
s + 3-ty przykład jest niewiarygodnie wolny i zużywa dużo pamięci, ponieważArray
trzeba zbudować dwa s pośrednie + 3 przykład może być użyty tylkounion
ze znanym liczbaArray
s w czasie kompilacji.Set
jest droga, aby przejść tutajZa pomocą zestawu (ECMAScript 2015) będzie to tak proste:
źródło
const array3 = [...new Set(array1.concat(array2))]
Oto nieco inne podejście do pętli. Dzięki niektórym optymalizacjom w najnowszej wersji Chrome jest to najszybsza metoda rozwiązania połączenia dwóch tablic (Chrome 38.0.2111).
http://jsperf.com/merge-two-arrays-keeping-only-unique-values
while loop: ~ 589k ops / s
filtr: ~ 445k ops / s
lodash: 308k ops / s
dla pętli: 225k ops / s
Komentarz wskazywał, że jedna z moich zmiennych konfiguracyjnych powodowała, że moja pętla wyprzedzała resztę, ponieważ nie musiała inicjować pustej tablicy, aby pisać. Zgadzam się z tym, więc przepisałem test, aby wyrównać szanse, i dodałem jeszcze szybszą opcję.
http://jsperf.com/merge-two-arrays-keeping-only-unique-values/52
W tym alternatywnym rozwiązaniu połączyłem macierz asocjacyjny jednej odpowiedzi, aby wyeliminować
.indexOf()
wywołanie w pętli, która spowalniała wiele rzeczy w drugiej pętli, i uwzględniłem niektóre inne optymalizacje, które inni użytkownicy sugerowali również w swoich odpowiedziach .Najlepsza odpowiedź tutaj z podwójną pętlą dla każdej wartości (i-1) jest nadal znacznie wolniejsza. lodash wciąż ma się dobrze i nadal polecam go każdemu, kto nie ma nic przeciwko dodaniu biblioteki do swojego projektu. Dla tych, którzy nie chcą, moja pętla while jest nadal dobrą odpowiedzią, a odpowiedź filtra ma tutaj bardzo mocne wyniki, bijąc wszystko na moich testach z najnowszym Canary Chrome (44.0.2360) od tego pisania.
Sprawdź odpowiedź Mike'a i odpowiedzi Dan Stocker jeśli chcesz krok to wycięcie w prędkości. To zdecydowanie najszybszy ze wszystkich wyników po przejściu prawie wszystkich realnych odpowiedzi.
źródło
Możesz to zrobić po prostu za pomocą ECMAScript 6,
źródło
Array.from(new Set(array1.concat(array2)))
.tsconfig.json
, możesz dodać"downlevelIteration": true
docompilerOptions
.Znacznie lepsza funkcja scalania tablic.
źródło
var test = ['a', 'b', 'c']; console.log(test);
wydrukuje["a", "b", "c", merge: function]
Wrzucam tylko dwa centy.
Jest to metoda, której często używam, wykorzystuje obiekt jako tabelę haszowania do sprawdzania duplikatów. Zakładając, że skrót to O (1), to działa on w O (n), gdzie n oznacza a. Długość + b. Długość. Szczerze mówiąc, nie mam pojęcia, w jaki sposób przeglądarka wykonuje skrót, ale działa dobrze na wielu tysiącach punktów danych.
źródło
String()
funkcja w javascript. Co może działać dla prymitywnych wartości (aczkolwiek w przypadku kolizji między typami), ale nie jest to dobre dopasowanie do tablic obiektów.Wystarczy omijać zagnieżdżone pętle (O (n ^ 2)) i
.indexOf()
(+ O (n)).źródło
Uproszczona najlepsza z tej odpowiedzi i zamieniła ją w przyjemną funkcję:
źródło
Dlaczego nie używasz przedmiotu? Wygląda na to, że próbujesz wymodelować zestaw. Nie zachowa to jednak porządku.
źródło
if (!set1.hasOwnProperty(key))
?Najlepszym rozwiązaniem...
Możesz sprawdzić bezpośrednio w konsoli przeglądarki, naciskając ...
Bez duplikatu
Z duplikatem
Jeśli chcesz bez duplikatu, możesz wypróbować lepsze rozwiązanie stąd - kod krzyku .
Wypróbuj konsolę przeglądarki Chrome
Wynik:
źródło
Mój półtora grosza:
źródło
Możesz to osiągnąć po prostu używając Underscore.js's>> uniq :
Wydrukuje [„Vijendra”, „Singh”, „Shakya”] .
źródło
W przypadku ES6 tylko jedna linia:
źródło
Wiem, że to pytanie nie dotyczy szeregu obiektów, ale tutaj szukają.
dlatego warto dodać przyszłym czytelnikom właściwy sposób łączenia, a następnie usuwania duplikatów
tablica obiektów :
źródło
Implementacja
indexOf
metody dla innych przeglądarek pochodzi z MDCźródło
from
parametru btw?indexOf
. Wyczyściłem kod, usuwając skomentowaną część. @meder - jeszcze raz dziękuję.Nowe rozwiązanie (które wykorzystuje
Array.prototype.indexOf
iArray.prototype.concat
):Stosowanie:
Array.prototype.indexOf (dla przeglądarki Internet Explorer):
źródło
Można to zrobić za pomocą Ustaw.
źródło
Jest tak wiele rozwiązań łączenia dwóch tablic. Można je podzielić na dwie główne kategorie (z wyjątkiem korzystania z bibliotek stron trzecich, takich jak lodash lub underscore.js).
a) połącz dwie tablice i usuń zduplikowane elementy.
b) odfiltruj elementy przed ich połączeniem.
Połącz dwie tablice i usuń zduplikowane elementy
Łączenie
Zjednoczenie
Istnieje wiele sposobów ujednolicenia tablicy, osobiście sugeruję poniżej dwie metody.
Filtruj elementy przed ich połączeniem
Istnieje również wiele sposobów, ale osobiście sugeruję poniższy kod ze względu na jego prostotę.
źródło
źródło
Zaletą tego jest wydajność i że ogólnie rzecz biorąc, pracując z tablicami, łączysz metody takie jak filtr, mapa itp., Więc możesz dodać tę linię, a ona połączy i deduplikuje tablicę2 z tablicą1 bez potrzeby odwoływania się do późniejszych jeden (gdy łączysz metody, których nie masz), przykład:
(Nie lubię zanieczyszczać prototypu Array.prototype i to byłby jedyny sposób na respektowanie łańcucha - zdefiniowanie nowej funkcji go zepsuje - więc myślę, że coś takiego jest jedynym sposobem na osiągnięcie tego)
źródło
Możesz spróbować:
źródło
Funkcjonalne podejście z ES2015
Zgodnie z podejściem funkcjonalnym a
union
dwóchArray
s jest tylko kompozycjąconcat
ifilter
. Aby zapewnić optymalną wydajność, korzystamy z rodzimegoSet
typu danych, który jest zoptymalizowany do wyszukiwania właściwości.W każdym razie kluczowym pytaniem w połączeniu z
union
funkcją jest sposób traktowania duplikatów. Możliwe są następujące permutacje:Dwie pierwsze kombinacje są łatwe w obsłudze dzięki jednej funkcji. Jednak dwa ostatnie są bardziej skomplikowane, ponieważ nie można ich przetwarzać, o ile polegają na
Set
wyszukiwaniu. Ponieważ przejście na zwykłeObject
wyszukiwanie starych właściwości pociągnęłoby za sobą poważny spadek wydajności, następująca implementacja ignoruje trzecią i czwartą permutację. Trzeba będzie zbudować osobną wersjęunion
do ich obsługi.Odtąd implementacja
unionn
funkcji, która akceptuje dowolną liczbę tablic (zainspirowana komentarzami naomika), staje się trywialna :Okazuje się, że
unionn
jest to po prostufoldl
(akaArray.prototype.reduce
), które przyjmujeunion
za swój reduktor. Uwaga: Ponieważ implementacja nie korzysta z dodatkowego akumulatora, zgłosi błąd, gdy zastosujesz go bez argumentów.źródło
flip
inotf
nie jestem używany.unionBy
Przewiduj także szczegóły implementacji wycieków (wymaga niejawnej wiedzy oSet
typie). Przydałoby się coś takiego:union = unionBy (apply)
iunionci = unionBy (p => x => p(x.toLowerCase()))
. W ten sposób użytkownik po prostu wysyła dowolną wartość grupowaniap
- tylko pomysł ^ _ ^zs
deklaracja zmiennej również nie mavar
/let
słowo kluczoweze względu na to ... oto rozwiązanie z jedną linią:
Nie jest szczególnie czytelny, ale może pomóc komuś:
Set
.Set
tablicy na tablicę.sort()
Funkcja jest stosowana do nowej tablicy.źródło
reduce()
możesz użyćArray.from(set)
DeDuplicate single lub Scal i DeDuplicate wiele tablic wejściowych. Przykład poniżej.
using ES6 - Ustaw, dla destrukcji
Napisałem tę prostą funkcję, która przyjmuje wiele argumentów tablicowych. Robi się prawie tak samo jak powyższe rozwiązanie, ma tylko bardziej praktyczny przypadek użycia. Ta funkcja nie łączy zduplikowanych wartości tylko w jednej tablicy, dzięki czemu może je usunąć na późniejszym etapie.
DEFINICJA KRÓTKIEJ FUNKCJI (tylko 9 linii)
UŻYJ PRZYKŁADU CODEPEN :
źródło
arr.map
tu korzystać ? Używasz go jakoforeach
, ponieważ wynik jest ignorowanyźródło
źródło