Data uit een Array filteren: select en detect

Geplaatst op 02/02/2012 in Ruby and Rails

Soms heb je data in een Array zitten die je eruit wilt filteren. Om dit voor elkaar te krijgen heb je een hoop verschillende manieren. De meest gebruikte is een for- of each-loop. Dit zijn echter niet de meest handige manieren. In deze Atom zal ik laten zien wat je het beste kunt doen om Arrays te filteren.


Stel we hebben een Array met een aantal User Models, oftewel: een Array met een hoop gebruikers. Hier willen we een aantal gebruikers uit selecteren. Ik deel het in twee onderdelen op: meerdere gebruikers selecteren en de eerste gebruiker selecteren.

Meerdere gebruikers selecteren

We willen uit deze Array een aantal gebruikers halen die de rol ‘admin’ hebben. Dit kan je op een aantal manieren doen.

Allereerst de manier die de meeste beginners gebruiken. We gaan een each-loop gebruiken om door de Array heen te gaan en stoppen alle admins in een nieuwe array. In ons voorbeeld is de Array met gebruikers de @users variabele.

admins = []
@users.each do |user|
  admins << user if user.role == "admin"
end

Nu zitten alle admins in de admins Array. Het werkt dus. Maar dat zijn maarliefst 4 regels voor iets vrij simpels. Dat kan beter! In Ruby heb je hiervoor de select method. Hiermee kun je verschillende objecten in een Array selecteren. Om hetzelfde voor elkaar te krijgen als hierboven doe je het volgende:

admins = @users.select { |user| user.role == "admin" }

Tada! Alle admins zitten erin. Met 1 regel krijg je dus precies hetzelfde voor elkaar.

Eerste gebruiker selecteren

Het selecteren van meerdere admin in de Array is dus vrij simpel. Maar wat als je alleen de eerste admin die je tegenkomt wilt selecteren? Je kunt dan het volgende doen:

admin = @users.select { |user| user.role == "admin" }.first

Of:

admin = nil
@users.each do |user|
  if user.role == "admin"
    admin = user
    break
  end
end

In het eerste voorbeeld gebruiken we select. Nadeel hierbij is dat hij door de hele Array heen zal gaan. Als de admin al op de eerste iteratie zit, zal hij toch door alle objecten zoeken. Erg inefficiënt natuurlijk. Bij het tweede voorbeeld is dit al wat efficiënter, omdat er een break gebeurt als de admin is gevonden. Alleen: wat is dat lelijk! Daar moet toch iets beters voor zijn?! Natuurlijk is dat er!

admin = @users.detect { |user| user.role == "admin" }

Tada! De eerste admin wordt in de admin variabele gestopt en er zal niet verder door de Array worden gezocht. Simpel toch?

Conclusie

Maak dus goed gebruik van select om meerdere objecten uit een Array te halen en detect om het eerste object eruit te halen. Er zijn zoveel keren dat een each-loop wordt gebruikt voor iets waar een simpele Array method gebruikt kan worden. Bekijk daarom de Ruby documentatie over de Array voor alle handige methods. Het gaat je een hoop tijd schelen als je ze onder de knie hebt.

Edit: Bekijk de eerste comment voor een link naar de detect method.

Comments (1)

Geplaatst op 02/02/2012 om 22:30

Als je je misschien afvraagt waarom detect niet in de Array documentatie zit: neem dan een kijkje bij de Enumerable. Hierin staan een hoop extra handige functies die je op Array kunt aanroepen.

Place a new comment

To place a comment, please log in via:
Het is snel en gemakkelijk. Kies een website waarmee je wilt inloggen en je kunt meteen reageren. Geen gedoe met wachtwoorden en een speciaal account bij ons.
Deze website maakt veelvuldig gebruik van JavaScript. U heeft dit uitstaan.