2016-07-09 13 views
0

Ich habe ein Array von Hashes, wobei jeder Hash eine Liste von URL-Parametern von URI :: decode_www_form ist. Ich möchte Duplikate in diesem Array entfernen, so dass alle Hashes innerhalb des Arrays eindeutige Parameterschlüssel haben.Wie Hashes aus Array entfernt werden, basierend darauf, ob alle Schlüssel in Hash mit einem anderen Hash übereinstimmen

Zum Beispiel, wenn ich

arr = [{"update" => "1", "reload" => "true"}, 
     {"update" => "5", "reload" => "false"}, 
     {"update" => "9", "reload" => "false"}, 
     {"update" => "7", "reload" => "true", "newvalue" => "11111"}, 
     {"page" => "1"}] 

ich erwarten würde ein Array nur enthalten haben:

arr = [{"update" => "1", "reload" => "true"}, 
     {"update" => "7", "reload" => "true", "newvalue" => "11111"}, 
     {"page" => "1"}] 

Wo die ersten drei Einträge Duplikate voneinander sind, so dass nur einer von ihnen halten, der vierte ist einzigartig, da er einen extra eindeutigen Schlüssel hat, den die ersten drei nicht hatten, und der fünfte ist einzigartig, da er nicht derselbe ist wie jeder von ihnen.

Wie würde ich versuchen, dieses Problem zu lösen?

+0

Wie haben Sie versucht, dieses Problem zu lösen? Und warum denkst du, dass die ersten drei Duplikate sind? Sie sind alle verschieden. – vgoff

+0

@vgoff Ihre Schlüssel sind die gleichen, die ich versuche, Duplikate zu entfernen. –

+0

Sie können die Frage bearbeiten, um das zu verdeutlichen, anstatt Einträge zu eindeutigen Schlüsseln .. Ich verließ mich nicht auf den Titel, der diesen Hinweis so stark gibt, wie ich sollte. :( – vgoff

Antwort

1

Man könnte es so lösen:

tmp = {} 
b = arr.select do |h| 
    if tmp[h.keys] 
    false 
    else 
    tmp[h.keys] = true 
    true 
    end 
end 
+0

Könnten Sie Ihrer Antwort ein wenig mehr hinzufügen, warum es für andere Leser funktioniert? –

+0

Der 'tmp'-Hash wird verwendet, um zu verfolgen, ob wir vorher eine bestimmte Menge von Schlüsseln gesehen haben Wenn wir "nil" haben, haben wir es vorher nicht gesehen, also setzen wir es auf 'tmp [h.keys] = true' und geben' true' zurück. Andernfalls geben wir nur "false" zurück. "Array # select" gibt nur die Werte zurück, die im bereitgestellten Block "true" zurückgeben - der erste Hash mit einem eindeutigen Schlüsselsatz. –

1
arr = [{"update" => "1", "reload" => "true"}, 
     {"update" => "5", "reload" => "false"}, 
     {"update" => "9", "reload" => "false"}, 
     {"update" => "7", "reload" => "true", "newvalue" => "11111"}, 
     {"page" => "1"}] 

arr.uniq(&:keys) 
    #=> [{"update"=>"1", "reload"=>"true"}, 
    # {"update"=>"7", "reload"=>"true", "newvalue"=>"11111"}, 
    # {"page"=>"1"}] 

die doc Siehe Array#uniq für den Fall, dass uniq einen Block nimmt. In der Tat macht Ruby die folgenden, um zu bestimmen, welche Elemente von arr wählen:

a = arr.map(&:keys) 
    #=> [["update", "reload"], 
    # ["update", "reload"], 
    # ["update", "reload"], 
    # ["update", "reload", "newvalue"], 
    # ["page"]] 

a.uniq 
    #=> [["update", "reload"], ["update", "reload", "newvalue"], ["page"]] 

arr.uniq(&:keys) hat die gleiche Wirkung wie:

arr.uniq { |h| h.keys } 
    #=> [{"update"=>"1", "reload"=>"true"}, 
    # {"update"=>"7", "reload"=>"true", "newvalue"=>"11111"}, 
    # {"page"=>"1"}] 

Viel Ansicht arr.uniq(&:keys) als nur eine kurze Hand Art und Weise des Schreibens der obige Ausdruck mit dem Block. Das ist in Ordnung, aber tatsächlich arr.uniq(&:keys) konvertiert die Methode (dargestellt durch das Symbol) :keys zu einem proc und ruft dann den proc auf.

+0

Danke für die Antwort, können Sie erklären, was & : Tut das in diesem Fall? –