2016-08-26 1 views
1

Ich habe zwei ArraysPerforming Vereinigung von zwei Arrays mit benutzerdefinierten Regeln

b = ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"] 

a = ["Jon Roberts", "Wil Koleva", "Lilian Joe", "Vic Jane", "Al Thomas"] 

Derzeit ich den Vereinigungsoperator auf diese beiden Arrays verwende, wie folgt aus: a | b. Wenn sie kombiniert werden, obwohl die Namen in jedem Array den gleichen Namen haben (sie verwenden nur die verkürzte Version des Namens), werden meine Namen kopiert.

Meine vorgeschlagene Lösung ist einfach wählen Sie das erste Vorkommen von ersten Initialen + Nachnamen als der Name, um die Union zu tun, aber ich erinnere mich nicht, gibt es Methoden in Ruby, die eine solche Operation durchführen können.

So das Ergebnis some_method(a | b) wird c zurückkehren, das ist nur:

["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"] 

Ich frage mich, wie ich über dies zu erreichen, gehen könnte?

+1

1) Koleva/Koleba? 2) Wenn Sie echte Ruby-Arrays schreiben, ist es einfacher, den Code zu testen. – tokland

+1

Ich vertraue dir, dass es mir nichts ausmacht, den Schnitt, den ich gemacht habe. Ich wollte den Kommentar von @ tokland ausarbeiten und dachte, es wäre leichter, den Schnitt zu machen, als zu versuchen, zu erklären, was er mit Worten meinte. Meinst du 'some_method (a, b)'? Wenn ja, bitte bearbeiten. –

+0

@CarySwoveland danke! – theGreenCabbage

Antwort

1
b = ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"] 
a = ["Jon Roberts", "Wil Koleva", "Lilian Joe", "Vic Jane", "Al Thomas"] 

r =/
    \s   # match a space 
    [[:alpha:]]+ # match > 0 alphabetic characters 
    \z   # match end of string 
    /x   # free-spacing regex definition mode 

(b+a).uniq { |str| [str[0], str[r]] } 
    #=> ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"] 

Dadurch wird die Form des Verfahrens verwendet Array#uniq, die einen Block beschäftigt.

können Sie alternativ (b|a).uniq { |str| [str[0], str[r]] }

Die Schritte schreiben sind wie folgt.

c = b+a 
    # => ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas", 
    # "Jon Roberts", "Wil Koleva", "Lilian Joe", "Vic Jane", "Al Thomas"] 

Das erste Element des c zu dem Block übergeben wird

str = c.first 
    #=> "John Roberts" 

so die Blockberechnung

sind
[str[0], str[r]] 
    #=> ["J", " Roberts"] 

Die Berechnungen für alle anderen Elemente der c ähnlich ist.Das Ergebnis ist, dass

c.uniq { |str| [str[0], str[r]] } 

äquivalent ist, die ersten Elemente der c zur Auswahl, wenn sie auf [<first name initial>, <last name>] umgewandelt, die d ein Element des Arrays entsprechen, wo

d = [["J", "Roberts"], ["W", "Koleva"], ["L", "Joe"], ["V", "Jane"], ["A", "Thomas"], 
    ["J", "Roberts"], ["W", "Koleva"], ["L", "Joe"], ["V", "Jane"], ["A", "Thomas"]].uniq 
    #=> [["J", "Roberts"], ["W", "Koleva"], ["L", "Joe"], ["V", "Jane"], ["A", "Thomas"]] 

Pascal vorgeschlagen, dass es besser wäre, für uniq ‚s Block eine Zeichenfolge zurück:

{ |str| "#{str[0]} #{str[r]}" } 

(zB "J Roberts"), die anstelle geschrieben werden könnte

{ |str| str.sub(/(?<=.)\S+/,"") } 

Die Einbeziehung des Raumes nach dem ersten Anfang ist optional (beispielsweise "JRoberts" würde auch).

+0

Tut mir leid, ich bin neu in Ruby. Kannst du mir erklären, was das ist? – theGreenCabbage

+0

Ich habe ein kleines Problem - dieses Skript scheint keine Vereinigung meiner beiden Sets zu haben, denn wenn ich JUST 'c = a | b '(mit keinem Code, der die Operation '.uniq' ausführt), bekomme ich die Verbindung, aber wenn ich dein Skript ausführe, fehlen einige Namen. Ich habe sowohl '(b + a) .uniq..' und' (b | a) .uniq..' versucht. – theGreenCabbage

+0

Sieht so aus, als ob ich 'str [1]' anstelle von 'str [0]' verwende, es funktioniert! – theGreenCabbage

1

Sicher, benutzen Sie einfach Enumerable#uniq mit einem Block:

c = (a | b).uniq do |full_name| 
    first_name, last_name = full_name.split(nil, 2) 
    [first_name[0], last_name] 
end 
+0

Aus irgendeinem Grund führte dieses Skript keine Union aus. – theGreenCabbage

1

Hinweis: die erste Iteration des Codes verwendet, um die Initialen statt abgekürzt Namen. Vielleicht können Sie das Konzept einer Name vorstellen? Es ist ein bisschen mehr Code als nur einen Block zu uniq, aber es kapselt alles gut zusammen.

class Name 
    def initialize(first, last) 
    @first, @last = first, last 
    end 

    def abbreviated 
    "#{@first[0]} #{@last}" 
    end 

    def eql?(other) 
    return false if !other.respond_to?(:abbreviated) 
    abbreviated == other.abbreviated 
    end 

    def hash 
    abbreviated.hash 
    end 

    def full 
    "#{@first} #{@last}" 
    end 
end 

a = Name.new('John', 'Roberts') 
b = Name.new('Jon', 'Roberts') 
c = Name.new('William', 'Koleva') 
d = Name.new('Wil', 'Koleva') 

x = [a, c] 
y = [b, d] 

p (y | x).map(&:full) 

Es ist erwähnenswert, dass abgekürzter Vorname nicht wirklich ausreicht, um die Gleichheit der Namen zu überprüfen.

Bedenken Sie:

Jim Jackson 
James Jackson 
Janine Jackson 
... 
Verwandte Themen