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
on 2006-11-26 00:48
on 2006-11-26 00:54
Brad Tilley wrote: > 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.lang.ruby/search?group=comp.lang.ruby&q=list+comprehension&qt_g=1&searchnow=Search+this+group
on 2006-11-26 01:08
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.
on 2006-11-26 01:22
Brad Tilley wrote:
> 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
on 2006-11-26 01:30
Quoting Mike Austin <noone@nowhere.com>: > [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.
on 2006-11-26 23:46
On 2006-11-25 18:47:26 -0500, Brad Tilley <rtilley@vt.edu> said:
> 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 }
Best,
James
on 2006-11-26 23:54
Hi -- On Mon, 27 Nov 2006, James Cunningham wrote: >> Ruby? > 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
on 2006-11-27 01:06
On 2006-11-26 17:52:37 -0500, dblack@wobblini.net said: >>> same = [x for x in new_data if x in old_data] >> class Array >> added = new_data.comprehend { |x| x if not old_data.include? x } > David 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] Best, James
on 2006-11-27 01:06
On 2006-11-26 19:01:53 -0500, James Cunningham <jameshcunningham@gmail.com> said: >>>> added = [x for x in new_data if x not in old_data] >>> recall where I found it. It's a cute little hack. >>> Then: >> > Best, > James Er, "your" meaning "Brad Tilley's". Best, James
on 2006-11-27 09:10
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
on 2006-11-27 09:36
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
on 2006-11-27 10:51
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?
on 2006-11-27 11:01
On 11/26/06, Mike Austin <noone@nowhere.com> wrote: > > Brad Tilley wrote: > <snip> > Because Ruby's select() returns a value, not just a boolean like in > Smalltalk, > > OT of course ;) ... this does not seem true for all Smalltalks, I am using Squeak and select: returns the filtered array, I am quite surprised that it worked differently before. <snip> Robert -- The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore all progress depends on the unreasonable man. - George Bernard Shaw
on 2006-11-27 14:01
On 2006-11-27 03:30:58 -0500, Robert Klemme <shortcutter@googlemail.com> said: >> > > 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 That's fair enough, but I think list comprehension is clearer than method chaining and one-liner array accumulation. I'm afraid a << x**2 if x % 2 == 1; a is perhaps just a little less elegant than x**2 if x % 2 == 1 I think the nicest thing about Ruby, though, is that it's even possible. Best, James
on 2006-11-27 15:23
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. :)
on 2006-11-28 05:45
James Cunningham wrote:
> end
Maybe I don't comprehend comprehending, but why the result/each instead
of map?
class Array
def comprehend
if block_given?
map{ |i| yield( i ) }.compact
else
self
end
end
end
or perhaps better
class Array
def comprehend( &block )
block ? map( &block ).compact : self
end
end
on 2006-11-28 06:15
On 2006-11-27 23:39:57 -0500, "Phrogz" <gavin@refinery.com> said: > class Array > def comprehend( &block ) > block ? map( &block ).compact : self > end > end The same. You're just cleverer than I am. ;) Best, James
on 2006-11-28 11:36
On 28.11.2006 05:39, Phrogz wrote: > class Array > def comprehend( &block ) > block ? map( &block ).compact : self > end > end This could go into Enumerable instead. There is no special Array functionality involved. Kind regards robert
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.