114 Stimmen

Gibt es in Ruby eine Array-Methode, die 'select' und 'map' kombiniert?

Ich habe ein Ruby-Array, das einige String-Werte enthält. Das muss ich tun:

  1. Alle Elemente finden, die einem Prädikat entsprechen
  2. Durchlaufen Sie die übereinstimmenden Elemente durch eine Transformation
  3. Rückgabe der Ergebnisse als Array

Im Moment sieht meine Lösung wie folgt aus:

def example
  matchingLines = @lines.select{ |line| ... }
  results = matchingLines.map{ |line| ... }
  return results.uniq.sort
end

Gibt es eine Array- oder Enumerable-Methode, die Select und Map in einer einzigen logischen Anweisung kombiniert?

9voto

Gishu Punkte 130442

Ich bin mir nicht sicher, ob es eine gibt. Die Aufzählbares Modul der Folgendes hinzufügt select y map zeigt keine an.

Sie müssten in zwei Blöcken zum select_and_transform Methode, was IMHO ein wenig unintuitiv wäre.

Man könnte sie natürlich auch einfach aneinanderreihen, was besser lesbar wäre:

transformed_list = lines.select{|line| ...}.map{|line| ... }

3voto

Sk. Irfan Punkte 279

Einfache Antwort:

Wenn Sie n Datensätze haben, und Sie möchten select y map je nach Bedingung dann

records.map { |record| record.attribute if condition }.compact

Hier, Attribut ist, was auch immer Sie wollen aus dem Datensatz und Bedingung können Sie eine beliebige Prüfung setzen.

kompakt ist, um die unnötigen Nullen zu löschen, die aus der if-Bedingung stammen

2voto

Daniel O'Hara Punkte 13037

Nein, aber Sie können es so machen:

lines.map { |line| do_some_action if check_some_property  }.reject(&:nil?)

Oder noch besser:

lines.inject([]) { |all, line| all << line if check_some_property; all }

2voto

fotanus Punkte 18937

Ich denke, dass dieser Weg besser lesbar ist, weil er die Filterbedingungen und den zugeordneten Wert aufteilt und gleichzeitig deutlich macht, dass die Aktionen miteinander verbunden sind:

results = @lines.select { |line|
  line.should_include?
}.map do |line|
  line.value_to_map
end

Und, in Ihrem speziellen Fall, eliminieren Sie die result Variable insgesamt:

def example
  @lines.select { |line|
    line.should_include?
  }.map { |line|
    line.value_to_map
  }.uniq.sort
end

1voto

Jörg W Mittag Punkte 349574
def example
  @lines.select {|line| ... }.map {|line| ... }.uniq.sort
end

In Ruby 1.9 und 1.8.7 können Sie Iteratoren auch verketten und umhüllen, indem Sie ihnen einfach keinen Block übergeben:

enum.select.map {|bla| ... }

Aber das ist in diesem Fall nicht wirklich möglich, da die Typen der Blockrückgabewerte von select y map nicht übereinstimmen. Es macht mehr Sinn für so etwas wie dies:

enum.inject.with_index {|(acc, el), idx| ... }

AFAICS, das Beste, was Sie tun können, ist das erste Beispiel.

Hier ist ein kleines Beispiel:

%w[a b 1 2 c d].map.select {|e| if /[0-9]/ =~ e then false else e.upcase end }
# => ["a", "b", "c", "d"]

%w[a b 1 2 c d].select.map {|e| if /[0-9]/ =~ e then false else e.upcase end }
# => ["A", "B", false, false, "C", "D"]

Aber was Sie wirklich wollen ist ["A", "B", "C", "D"] .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X