2015-11-06 8 views
7

Ich versuche, nicht doppelte Werte aus einer Liste zu finden, z.elixir-lang Suchen von nicht-duplizierten Elementen in einer Liste

ursprüngliche Liste:

iex> list = [2, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, 10, 10, 10] 
[2, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, 10, 10, 10] 

iex> unique = Enum.uniq(list) 
[2, 3, 4, 5, 6, 7, 8, 9, 10] 

iex> nondupes = unique -- Enum.uniq(list -- unique) 
[2, 3, 5, 7] 

Ergebnis: [2, 3, 5, 7]

Ich habe mich gefragt, ob es eine bessere Art und Weise war dies in Elixier zu erreichen/erlang

Antwort

10

Ein weitere Methode (nicht unbedingt besser), die für große Daten schneller sein könnte, besteht darin, eine Karte von Elementen zu ihren Zählungen zu erstellen und diejenigen auszuwählen, bei denen der Zählwert 1:

ist

Dies sollte Laufzeit O(n * log(n)) anstelle der O(n^2) Ihre Lösung erfordert (die Subtraktion sollte quadratisch sein, wenn die gesamte Eingabe bereits eindeutig ist).

+2

Sie können auch 'reduce' mit zwei Sätzen, ein zu halten alle Einträge, die Sie so weit und ein anderer mit den Einzigen gesehen haben. Für jedes Element, wenn es in der Liste gesehen wird, sollten Sie es aus uniq entfernen, sonst fügen Sie beiden hinzu. –

+2

Nur eine kleine Verbesserung: Im Reduzierungsschritt können Sie auch '& Dict.update (& 2, & 1, 1, Fn x -> x + 1 Ende)' anstelle des manuellen Get/Put verwenden. –

0

REDO

(Wie Paweł wies darauf hin, ich habe nicht die Frage beantworten, sondern adressiert nur die uniqifying Bit. Also ging ich über Bord für Spaß unten.)

hier ein rein rekursiv ist, Single-Pass, Matching-only-Methode:

-module(nondupes). 
-export([leave_uniques/1]). 

leave_uniques(L) -> 
    lists:reverse(lu(lists:sort(L))). 

lu(L = [H,H|_]) -> lu(L, [], dupe); 
lu([H|T])  -> lu(T, [H], solo). 

lu([H,H], A, dupe)   -> A; 
lu([_,H], A, dupe)   -> [H|A]; 
lu([H,H], A, solo)   -> A; 
lu([P,H], A, solo)   -> [P,H|A]; 
lu([H | T = [H|_]], A, dupe) -> lu(T, A, dupe); 
lu([_ | T], A, dupe)   -> lu(T, A, solo); 
lu([H | T = [H|_]], A, solo) -> lu(T, A, dupe); 
lu([P | T], A, solo)   -> lu(T, [P|A], solo). 

Wenn Erfahrungen aus der Vergangenheit ein Richter ist, ist es wahrscheinlich mehr performant auf große Listen als Liste/set Subtraktion - aber die Erfahrungen der Vergangenheit sagt mir auch, dass die meisten der Zeit pe Rformance ist wirklich kein großes Problem. Wie auch immer, das war irgendwie unterhaltsam.

Verwendung:

2> nondupes:leave_uniques([2, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, 10, 10, 10]). 
[2,3,5,7] 
+0

Ich glaube nicht, dass dies die Frage beantwortet - das ist im Grunde eine Neuimplementierung von 'Enum.uniq'. Sehen Sie sich die Frage und die erwartete Ausgabe der Routine an. –

+0

@ PawełObrok Tatsächlich. Das vollständige Formular, das Sie möchten, wird nur durch die Verwendung von Mengen-/Listenoperationen vervollständigt. Also, um Ihre Frage so vollständig wie möglich zu beantworten, ist hier eine reine Routine, die einzigartige Mitglieder in einem einzigen Durchgang extrahiert. Hoffe es gibt dir ein Kichern. :-) – zxq9

Verwandte Themen