Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Ruby (http://www.velocityreviews.com/forums/f66-ruby.html)
-   -   ruby and list comprehension (http://www.velocityreviews.com/forums/t835806-ruby-and-list-comprehension.html)

Brad Tilley 11-25-2006 11:47 PM

ruby and list comprehension
 
In Python, I can do this to arrays:

added = [x for x in new_data if x not in old_data]
removed = [x for x in old_data if x not in new_data]
same = [x for x in new_data if x in old_data]

I believe this is known as list comprehension in Python. How is this done in
Ruby?

Thanks,
Brad


Timothy Hunter 11-25-2006 11:53 PM

Re: ruby and list comprehension
 
Brad Tilley wrote:
> In Python, I can do this to arrays:
>
> added = [x for x in new_data if x not in old_data]
> removed = [x for x in old_data if x not in new_data]
> same = [x for x in new_data if x in old_data]
>
> I believe this is known as list comprehension in Python. How is this done in
> Ruby?
>
> Thanks,
> Brad
>
>

This question comes up from time to time. You can search the archives of
comp.lang.ruby on Google Groups for "list comprehension" to find the
previous threads on this topic.

http://groups.google.com/group/comp....rch+this+group


Louis J Scoras 11-26-2006 12:06 AM

Re: ruby and list comprehension
 
On 11/25/06, Brad Tilley <rtilley@vt.edu> wrote:

> In Python, I can do this to arrays:
>
> added = [x for x in new_data if x not in old_data]
> removed = [x for x in old_data if x not in new_data]
> same = [x for x in new_data if x in old_data]


Short answer:

added = new_data.reject {|i| old_data.include? i }
removed = old_data.reject {|i| new_data.include? i }
same = new_data.select {|i| old_data.include? i }

Provided ordering isn't important here, you can do the same thing with
set operations.

require 'set'

old_data = old_data.to_set
new_data = new_data.to_set

added = new_data - old_data
removed = old_data - new_data
same = new_data.intersection(old_data)

Note those returns sets, not arrays.


--
Lou.


Mike Austin 11-26-2006 12:19 AM

Re: ruby and list comprehension
 
Brad Tilley wrote:
> In Python, I can do this to arrays:
>
> added = [x for x in new_data if x not in old_data]
> removed = [x for x in old_data if x not in new_data]
> same = [x for x in new_data if x in old_data]
>
> I believe this is known as list comprehension in Python. How is this done in
> Ruby?
>
> Thanks,
> Brad


Because Ruby's select() returns a value, not just a boolean like in Smalltalk,
you can do the following:

[1,2,3].select { |x| ![2,3,4].include? x }
[2,3,4].select { |x| ![1,2,3].include? x }
[1,2,3].select { |x| [2,3,4].include? x }

You can also use Array operators:

[1,2,3] - [2,3,4]
[2,3,4] - [1,2,3]
[1,2,3] & [2,3,4]


Mike

Brad Tilley 11-26-2006 12:29 AM

Re: ruby and list comprehension
 
Quoting Mike Austin <noone@nowhere.com>:

> Because Ruby's select() returns a value, not just a boolean like in
> Smalltalk,
> you can do the following:
>
> [1,2,3].select { |x| ![2,3,4].include? x }
> [2,3,4].select { |x| ![1,2,3].include? x }
> [1,2,3].select { |x| [2,3,4].include? x }
>
> You can also use Array operators:
>
> [1,2,3] - [2,3,4]
> [2,3,4] - [1,2,3]
> [1,2,3] & [2,3,4]


Thanks for all the examples guys! That's great stuff.


dblack@wobblini.net 11-26-2006 10:52 PM

Re: ruby and list comprehension
 
Hi --

On Mon, 27 Nov 2006, James Cunningham wrote:

> On 2006-11-25 18:47:26 -0500, Brad Tilley <rtilley@vt.edu> said:
>
>> In Python, I can do this to arrays:
>>
>> added = [x for x in new_data if x not in old_data]
>> removed = [x for x in old_data if x not in new_data]
>> same = [x for x in new_data if x in old_data]
>>
>> I believe this is known as list comprehension in Python. How is this done
>> in
>> Ruby?
>>
>> Thanks,
>> Brad

>
> I found this while web searching for the same thing recently; I can't recall
> where I found it. It's a cute little hack.
>
> class Array
> def comprehend
> return self unless block_given?
> result = []
> self.each { |i| result.push yield(i) }
> result.compact
> end
> end
>
> Then:
>
> added = new_data.comprehend { |x| x if not old_data.include? x }
> removed = old_data.comprehend { |x| x if not new_data.include? x }
> same = new_data.comprehend { |x| x if old_data.include? x }


I'm not getting how that's better than:

added = new_data.select {|x| not old_data.include?(x) }

(or the reject equivalent) and so on.


David

--
David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org


Martin DeMello 11-27-2006 08:09 AM

Re: ruby and list comprehension
 
On 11/27/06, James Cunningham <jameshcunningham@gmail.com> wrote:
>
> added = new_data.comprehend { |x| x if not old_data.include? x }
> removed = old_data.comprehend { |x| x if not new_data.include? x }
> same = new_data.comprehend { |x| x if old_data.include? x }


I wrote http://zem.novylen.net/ruby/fproduct.rb a while ago to emulate
list comprehensions in ruby - for example:

for x,y,z in product 1..40,
1..40, proc {|x,y| x <= y},
1..40, proc {|x,y,z| x**2 + y**2 == z**2}
p [x,y,z]
end

The benefit is that the filters do get applied in order (sorted on
arity), so that it doesn't generate all the combinations first and
then filter.

martin


Robert Klemme 11-27-2006 08:30 AM

Re: ruby and list comprehension
 
On 27.11.2006 01:01, James Cunningham wrote:
> On 2006-11-26 17:52:37 -0500, dblack@wobblini.net said:
>> I'm not getting how that's better than:
>>
>> added = new_data.select {|x| not old_data.include?(x) }
>>
>> (or the reject equivalent) and so on.


> I should have clarified. In your example there's no difference, but the
> above gives a general replacement for list comprehensions.
>
> irb(main):018:0> (1..25).to_a.comprehend { |x| x**2 if not x % 2 == 0 }
> => [1, 9, 25, 49, 81, 121, 169, 225, 289, 361, 441, 529, 625]


Frankly, I am not sure I find this better than using the built in methods:

irb(main):001:0> (1..25).inject([]) {|a,x| a << x**2 unless x % 2 == 0; a}
=> [1, 9, 25, 49, 81, 121, 169, 225, 289, 361, 441, 529, 625]

irb(main):002:0> (1..25).inject([]) {|a,x| a << x**2 if x % 2 == 1; a}
=> [1, 9, 25, 49, 81, 121, 169, 225, 289, 361, 441, 529, 625]

irb(main):003:0> (1..25).select {|x| x % 2 == 1}.map! {|x| x**2}
=> [1, 9, 25, 49, 81, 121, 169, 225, 289, 361, 441, 529, 625]

Kind regards

robert

piggybox 11-27-2006 09:49 AM

Re: ruby and list comprehension
 
I've always thought list comprehension is just a bunch of
map/filter/... transformation until I saw the following version of
permutation:

in Haskell:
permutation [] = [[]]
permutation xs = [x:ys | x <- xs, ys <- permutation (delete x xs)]

in Erlang:
permutation([]) -> [[]];
permutation(L) -> [[H|T] || H <- L, T <- permutation(L--[H])].

really neat, isn't it?


Devin Mullins 11-27-2006 02:21 PM

Re: ruby and list comprehension
 
piggybox wrote:
> in Haskell:
> permutation [] = [[]]
> permutation xs = [x:ys | x <- xs, ys <- permutation (delete x xs)]
>
> in Erlang:
> permutation([]) -> [[]];
> permutation(L) -> [[H|T] || H <- L, T <- permutation(L--[H])].
>
> really neat, isn't it?

Yes. :)



All times are GMT. The time now is 03:05 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.