From: Brian Mitchell Date: 2006-04-21T03:04:40+09:00 Subject: Re: Converting IP range to array of IP's On 4/20/06, Brian Mitchell wrote: > On 4/20/06, Kris wrote: > > I'm looking to convert an IP string (ranges, subnet masks or wild-carded > > IP's) in to an array of IP strings: > > > > eg. "192.168.1.1 - 192.168.1.5" => ["192.168.1.1", "192.168.1.2", > > "192.168.1.3", "192.168.1.4", "192.168.1.5"] > > > > Before I embark on this, is there already a ruby class that does it or > > some of this? > > Other's solutions should work great but just for fun and enlightenment > I wrote my own little implementation of a simple list comprehension in > Haskell and then ported it to Ruby. This simple piece of code allows > you to expand more arbitrary ranges and might be good for more things > than just IP addresses. > > # Condensed ruby version of this haskell code > # > # [[a,b,c,d] | a <- [192], b <- [168], c <- [0,1], d <- [1..10]] > # > # non-sugared notation: > # [192] >>= \a -> > # [168] >>= \b -> > # [0,1] >>= \c -> > # [1..10] >>= \d -> > # return [a,b,c,d] > > class Array > def expand(i = 0, *a) > return [a] if i == size > self[i].to_a.map {|x| > expand(i+1, *(a + [x])) > }.inject([]) {|m, a| m + a} > end > end A few redundancies to fix (my original code didn't use map but a custom method Array#bind. The to_a is no longer needed: class Array def expand(i = 0, *a) return [a] if i == size self[i].map {|x| expand(i+1, *(a + [x])) }.inject([]) {|m, x| m + x} end end This is what it used to look like: class Array def bind(&blk) map(&blk).inject([]) {|m, x| m+x} end def expand(i = 0, *a) return [a] if i == size self[i].bind {|x| expand(i+1, *(a + [x]))} end end Note that bind could have the inject part split out into what Haskell calls a join but that just lead to name issues so I just inlined it. Brian.