2016-12-30 3 views
1

Ich habe eine enum, die ich verwende group_by mit.Gibt es einen einfachen Weg zu || Null-Muster-Match in Elixier?

Enum.group_by(my_list, fn x -> x.param end)

Das Ergebnis ist, dass sie es durch die Gruppen param Wert. Ich möchte, dass auf Muster Spiel schnell, so habe ich:

%{"a" => a, "b" => b, "c" => c } = Enum.group_by(my_list, fn x -> x.param end)

Aber das läuft in Probleme, wenn Liste fehlt entweder „a“, „b“ oder „c“ als params.

Beachten Sie, dass ich es auf eine Variable gesetzt und es wird in null führen, wenn ich auf sie zugreifen und es funktioniert nicht existieren:

grouped = Enum.group_by(my_list, fn x -> x.param end) 
grouped["a"] # this will show as nil or the result if it exists 

aber zur besseren Lesbarkeit, wollte ich nur dieses Muster und die Variablen verwenden. Ist das etwas, was in Elixir nicht unterstützt wird?

+0

Musterübereinstimmung _will_ fehlgeschlagen bei fehlenden Schlüsseln. Sie könnten '% {" a "=> nil," b "=> nil," c "=> nil}' mit dem Ergebnis von 'Enum.group_by' zusammenfassen, aber das ist wahrscheinlich noch schlimmer als die von Ihnen erwähnte Alternative. Sie könnten auch eine Funktion ähnlich wie "Map.take" machen, die die Werte bei bestimmten Schlüsseln zurückgibt und 'nil' zurückgibt, wenn der Schlüssel nicht vorhanden ist, und sie wie folgt verwenden:' [a, b, c] = my_take (Enum. group_by (...), ["a", "b", "c"]) '. – Dogbert

+0

Das, wonach Sie fragen, wird nicht unterstützt, aber vielleicht, wenn Sie Ihre Frage etwas erweitern (was wollen Sie mit den Daten machen? Warum wollen Sie 'nil's zurück bekommen? Wie sieht die Eingangsliste aus?) Sie könnten etwas breitere Vorschläge bekommen. –

Antwort

1

Die Mustererkennung dient zum selbstüberprüfenden Durchsetzungscode, nicht nur zum schnellen Abrufen von Werten. Ihr Code überprüft, ob alle angegebenen Schlüssel in der Karte enthalten sind. Wenn Sie eine solche Überprüfung nicht benötigen, verwenden Sie keinen Mustervergleich.

Zum Beispiel, lassen Sie uns zuerst das Ergebnis einer Variablen zuweisen (die in Elixir tatsächlich nicht variiert).

groups = Enum.group_by(my_list, fn x -> x.param end) 

Dann lassen Sie uns deсide, was wir damit machen wollen. Wollen wir die Gruppen bearbeiten? Lass es uns tun:

Enum.map(groups, fn({name, list}) -> process_group(name, list) end) 

Müssen wir die fehlenden Gruppen verarbeiten? Kein Problem:

missing_groups = Enum.filter(["a", "b", "c"], &(!Map.has_key?(groups, &1))) 
Enum.map(missing_groups, fn(name) -> process_missing_group(name) end) 

Möchten Sie nach Schlüsseln filtern? Das ist auch kein Problem:

# First variant: 
filtered_groups = Enum.into(Enum.filter(groups, fn({k, v}) -> k in ["a", "b", "c"] end), %{}) 
# Second variant: 
filtered_groups = Map.drop(groups, ["d", "e", "f", "g", "h"]) 

Möchten Sie wirklich fehlende Schlüssel hinzufügen? Ok, wenn ja, dann lass es uns tun:

all_groups = Enum.into(["a", "b", "c"], %{}, &({&1, Map.get(groups, &1)})) 
process_all_groups(all_groups) 

Wie Sie sehen können, Muster für die Karte passend ist nicht wirklich nötig für jede dieser Aktion. Eigentlich brauchen Sie die Variablen überhaupt nicht, sie dienen lediglich der besseren Lesbarkeit.

Jetzt können Sie sagen "ok, ok, aber ich möchte verschiedene Aktionen für verschiedene Gruppen". Hier können Sie bei Bedarf auch die Mustervergleichsfunktion verwenden.

def process_group(name, nil), do: action_empty(name) 
def process_group("a", list), do: action_a(list) 
def process_group("b", list), do: action_b(list) 
def process_group(name, [x]), do: single_lement_action(name, x) 
def process_group(name, list), do: another_action(name, list) 

Sieht das wie, was Sie brauchen?

+0

Ich werde dies als Antwort akzeptieren, weil das, wonach ich frage, nicht möglich ist und dies nützliche Informationen darüber liefert, wie Elixier funktioniert –

Verwandte Themen