`
clark1231
  • 浏览: 254571 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Using select, reject, collect, inject and detect.

    博客分类:
  • ruby
阅读更多

 

Looping in Ruby seems to be a process of evolution for newcomers to the language. Newcomers will always find their way to the for loop almost immediately and when confronted with iterating an array, the first choice will generally be a for..in:

1
2
3
4
a = [1,2,3,4]
for n in a
  puts n
end

This works, but its not very… Ruby. The next stage of evolution will be using an iterator for the first time. So the for loop gets dropped all together and each is used. The Rubyist is born at this point:

1
2
3
a.each do |n|
  puts n
end

What I see next is a lot of conditional logic being used inside the each block. The logic is generally introduced to perform the following operations:

  1. Building a list of items from an array.
  2. Total the items in an array.
  3. Find an item in the array.

So if this is you, then stop. Ruby has plenty more iterators where each came from. Which one you should be using depends on what operation you are trying to perform. So let’s take a look at our previous list and see if we can find a more Ruby way to get them done.

Building a list of items from the array using select

For this operation you should be using select. The way select works is simple, it basically iterates through all the elements in your array and performs your logic on each one. If the logic returns TRUE, then it adds the item to a new array which it returns when the iteration is complete. Here’s an example:

1
2
a = [1,2,3,4]
a.select {|n| n > 2}

This will return the last two elements in the array: 3 and 4. Why? Because 3 and 4 are both greater than 2, which was the logic we placed in the block. It’s worth noting that select has an evil step sister named reject. This will perform the opposite operation of select. Logic which returns FALSE adds the item to the array that is returned. Here’s the same examples as before except we will swap select, with reject:

1
2
a = [1,2,3,4]
a.reject {|n| n > 2}

In this example the return value is [1,2] because these elements return false when the condition is tested.

I also have to mention another close sibling to select and reject; collect, which returns an array of values that are the RESULT of logic in the block. Previously we returned the item based on the result of the CONDITION in the block. So perhaps we need square the values in our array:

1
2
a = [1,2,3,4]
a.collect {|n| n*n}

This returns a new array with each item in our array squared.

Finally, note that using select, reject, and collect returns an array. If you want to return something different, because you are concatenating or totaling values, then check out inject.

Total the items in an array using inject

When you think of accumulating, concatenating, or totaling values in an array, then think of inject. The main difference between select and inject is that inject gives you another variable for use in the block. This variable, referred to as the accumulator, is used to store the running total or concatenation of each iteration. The value added to the accumulator is the result of the logic you place in the block. At the end of each iteration, whatever that value is, can be added to the accumulator. For example, let’s sum all the numbers together in our array:

1
2
a = [1,2,3,4]
a.inject {|acc,n| acc + n}

This will return 10. The total value of all the elements in our array. The logic in our block is simple: add the current element to the accumulator. Remember, you must dosomething to the accumulator in each iteration. If we had simply placed n in the block the final value of the accumulator would have been 4. Why? Because its the last value in the array and since we did not add it to the accumulator explicitly the accumulator would be replaced in each iteration.

You can also use a parameter with the inject call to determine what the default value for the accumulator is:

1
2
a = [1,2,3,4]
a.inject(10) {|acc,n| acc + n}

In this example the result is 20 because we assigned the accumulator an initial value of 10.

If you need to return a string or an array from inject, then you will need to treat the accumulator variable that way. You can use the default value parameter of inject to do this:

1
2
a = [1,2,3,4]
a.inject([]) {|acc,n| acc << n+n}

In this example I add n to itself and then append it to the accumulator variable. I initialized the accumulator as an empty array using the default value parameter.

Find an item in the array using detect

Our last example operation was to find an element in the array. Let’s just put it out there and say that other iterators could be used to select the correct value from the array, but I am going to show you how to use detect to round out our exploration of these iterators.

So let’s find the value 3 in our array using detect:

1
2
a = [1,2,3,4]
a.detect {|n| n == 3}

This returns 3. The value we were looking for. If the value had not been found, then the iterator returns nil.

So if your head is spinning at this point as to which iterator to use for when, then remember this:

  1. Use select or reject if you need to select or reject items based on a condition.
  2. Use collect if you need to build an array of the results from logic in the block.
  3. Use inject if you need to accumulate, total, or concatenate array values together.
  4. Use detect if you need to find an item in an array.

By using these iterators you will be one step closer to mastering… Ruby-Fu.

 

分享到:
评论

相关推荐

    refuse-,reject的用法区别参考.doc

    "refuse" 和 "reject" 是英语中表达拒绝的两个常用动词,它们在用法上存在一定的区别。首先,"refuse" 的含义通常较为直接,表示坚决地不接受或者不做某事,例如拒绝给予某人所需或所求的东西。它的语气相对较强,...

    Apache Hadoop 2.7.2

    The Hadoop portmapper is no longer required to run the gateway, and the gateway is now able to reject connections from unprivileged ports. The SecondaryNameNode, JournalNode, and DataNode web UIs ...

    nf_reject_ipv6.rar_Too Short_nf_reject_ipv4.ko

    IP header checks: fragment, too short.

    EurekaLog_7.5.0.0_Enterprise

    4)....Added "--el_injectjcl", "--el_createjcl", and "--el_createdbg" command-line options for ecc32/emake to inject JEDI/JCL debug info, create .jdbg file, and create .dbg file (Microsoft debug format...

    nft_reject_bridge.rar_return

    标题中的“nft_reject_bridge.rar_return”暗示了我们正在讨论与网络过滤和包处理相关的主题,特别是与Netfilter(NFT)框架下的拒绝规则和桥接(bridge)有关的内容。在Linux系统中,Netfilter是内核的一部分,用于...

    The Bias Against Creativity - Why People Desire But Reject Creative Ideas (Cornell, 1-1-2011)-计算机科学

    But Reject Creative Ideas Jennifer S. Mueller University of Pennsylvania, jennm@wharton.upenn.eduShimul Melwani University of North Carolina at Chapel Hill, shimul_melwani@kenan-flagler.unc.eduJack A....

    nf_reject.rar_run

    标题“nf_reject.rar_run”和描述中的“Select calibration to run for Linux v2.13.6.”暗示了我们正在处理一个与Linux内核相关的项目,特别是涉及到网络过滤和校准的部分。在这个场景中,“nf_reject”可能指的是...

    MicrosoftEdgeSetup.exe

    It comes with additional features like tracking prevention, personalized tab layouts, 4K streaming, reward points, and a choice to accept or reject targeted advertising. Since Microsoft has worked on...

    reject-用于Java和Android的依赖注入框架

    ** Reject 框架概述** `Reject` 是一个专为Java和Android开发设计的轻量级依赖注入(Dependency Injection,简称DI)框架。依赖注入是一种软件设计模式,它可以帮助开发者解耦组件,使得代码更易于测试和维护。通过...

    ipt_REJECT.rar_IS

    标题中的“ipt_REJECT.rar_IS”暗示我们正在讨论与iptables相关的拒绝策略,这在网络安全和Linux系统管理中是非常重要的一个方面。iptables是一个用于在Linux内核中实现包过滤和网络地址转换(NAT)的工具,它允许...

    Accept_Reject_Packets.zip_Destination

    "Accept_Reject_Packets.zip_Destination" 文件压缩包提供了一个示例代码,帮助我们理解如何让路由器根据特定条件接受或拒绝来自某个目的地的数据包。这个场景常见于网络安全、访问控制以及流量管理等应用。 1. **...

    java_ssm基于bs模式的医院在线挂号预约系统的设计与实现jsp毕业论文.doc

    The doctor module, on the other hand, allows medical professionals to manage their consultation schedules, approve or reject appointment requests, and maintain patient case records. Doctors can update...

    GetWebPics专业版2.9

    It will help you to collect your own galleries of celebrities, babies, cars, sexy bodies and many others. Build-in picture viewer, thumbnail viewer and fullscreen slideshow with transition effects ...

    基于asp.net(CS)企业员工考勤管理系统设计与实现.docx

    3. **Leave Management**: Allowing employees to request leaves, and managers to approve or reject them. 4. **Reporting**: Generating various attendance reports, such as tardiness reports, absence ...

    lodash underscore js库速查手册

    _.reduce(list, iterator, memo, [context]) Aliases: inject, foldl Also known as inject and foldl, reduce boils down a list of values into a single value. _.reduceRight(list, iterator, memo, [context]) ...

    nft_reject.rar_Apples

    标题中的“nft_reject.rar_Apples”暗示了这是一个与苹果(Apple)设备相关的软件更新或驱动程序包,其中可能包含对“nft_reject”功能的修改或增强。描述指出这是“Backlight Driver for Intel-based Apples”,这...

    nf_reject_ipv4.rar_Harder_skb

    标题 "nf_reject_ipv4.rar_Harder_skb" 指涉的是与网络过滤和IP路由相关的编程问题,特别是涉及到Linux内核中的网络子系统。描述 "ip_route_me_harder expects skb-&gt;dst to be set." 提示我们这个问题的核心在于`ip_...

    详解Spring Cloud Config采用Git存储时两种常用的配置策略

    春云配置中心Git存储策略详解 Spring Cloud Config是Spring Cloud体系中的一款配置中心组件,默认情况下采用Git存储来存储配置文件。今天,我们将详细介绍Spring Cloud Config采用Git存储时两种常用的配置策略。...

    Manning.Git.in.Practice.2014.9.pdf

    - **Reviewing Pull Requests**: Reviewers can comment on specific lines of code, suggest changes, and approve or reject the pull request. **Chapter 11: Hosting a Repository** - **Self-hosted Git ...

Global site tag (gtag.js) - Google Analytics