Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > ruby and list comprehension

Reply
Thread Tools

ruby and list comprehension

 
 
Brad Tilley
Guest
Posts: n/a
 
      11-25-2006
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

 
Reply With Quote
 
 
 
 
Timothy Hunter
Guest
Posts: n/a
 
      11-25-2006
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

 
Reply With Quote
 
 
 
 
Louis J Scoras
Guest
Posts: n/a
 
      11-26-2006
On 11/25/06, Brad Tilley <(E-Mail Removed)> 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.

 
Reply With Quote
 
Mike Austin
Guest
Posts: n/a
 
      11-26-2006
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
 
Reply With Quote
 
Brad Tilley
Guest
Posts: n/a
 
      11-26-2006
Quoting Mike Austin <(E-Mail Removed)>:

> 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.

 
Reply With Quote
 
dblack@wobblini.net
Guest
Posts: n/a
 
      11-26-2006
Hi --

On Mon, 27 Nov 2006, James Cunningham wrote:

> On 2006-11-25 18:47:26 -0500, Brad Tilley <(E-Mail Removed)> 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 | http://www.velocityreviews.com/forums/(E-Mail Removed)
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

 
Reply With Quote
 
Martin DeMello
Guest
Posts: n/a
 
      11-27-2006
On 11/27/06, James Cunningham <(E-Mail Removed)> 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

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      11-27-2006
On 27.11.2006 01:01, James Cunningham wrote:
> On 2006-11-26 17:52:37 -0500, (E-Mail Removed) 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
 
Reply With Quote
 
piggybox
Guest
Posts: n/a
 
      11-27-2006
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?

 
Reply With Quote
 
Devin Mullins
Guest
Posts: n/a
 
      11-27-2006
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.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
List comprehension in if clause of another list comprehension Vedran Furac( Python 4 12-19-2008 01:35 PM
Appending a list's elements to another list using a list comprehension Debajit Adhikary Python 17 10-18-2007 06:45 PM
List comprehension returning subclassed list type? Shane Geiger Python 4 03-25-2007 09:34 AM
(patch for Bash) list comprehension and filtering William Park Python 0 08-02-2004 08:22 AM
Mix lambda and list comprehension? Peter Barth Python 4 07-16-2003 11:20 PM



Advertisments