Data uit een Array filteren: select en detect
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.
Geplaatst op 02/02/2012 om 22:30
Als je je misschien afvraagt waarom
detectniet 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.