Array#uniq with block equivalent in Ruby 1.8.7 - ruby

Array#uniq has this behaviour in Ruby 1.9
c = [ "a:def", "a:xyz", "b:abc", "b:xyz", "c:jkl" ]
c.uniq {|s| s[/^\w+/]} #=> [ "a:def", "b:abc", "c:jkl" ]
It can take a block and give unique value with respect to what we give. But, this wont work in Ruby 1.8. How can I create this functionality in ruby 1.8?

Install Marc-André LaFortune's backports gem:
https://github.com/marcandre/backports
That has the block versions of 1.9.2's Array#uniq and Array#uniq!. Or if you don't want or need the whole thing, the parts are pretty well isolated so you can pull out just the pieces you need:
https://github.com/marcandre/backports/blob/master/lib/backports/1.9.2/array.rb#L99

It's easy to implement something like:
class Array
def uniq
ret, keys = [], []
each do |x|
key = block_given? ? yield(x) : x
unless keys.include? key
ret << x
keys << key
end
end
ret
end
end

Related

Get a Ruby hash with one element removed (non-destructive)

I need to get a new Ruby hash based on an existing hash but with one element removed and without affecting the original hash. I'm sure it's really simple, and I'm too much of a Ruby newbie to spot it.
For example, if I have plugh={:bar=>"bar", :baz=>"baz"} I want to be able to do something like xyzzy=plugh.some_magic_goes_here(:baz) and get xyzzy set to {:bar=>"bar"} without affecting plughin any way. How do I do it?
If you are not using active support, you can do the following:
xyzzy = plugh.reject { |k, _| k == :baz }
If you're using Rails (or at least ActiveSupport), then except is what you want:
xyzzy = plugh.except(:baz)
If you're not using Rails, the docs include the source code as well:
def except(*keys)
dup.except!(*keys)
end
def except!(*keys)
keys.each { |key| delete(key) }
self
end

How to randomly sort (scramble) an array in Ruby?

I'd like to have my array items scrambled.
Something like this:
[1,2,3,4].scramble => [2,1,3,4]
[1,2,3,4].scramble => [3,1,2,4]
[1,2,3,4].scramble => [4,2,3,1]
and so on, randomly
Built in now:
[1,2,3,4].shuffle => [2, 1, 3, 4]
[1,2,3,4].shuffle => [1, 3, 2, 4]
For ruby 1.8.6 (which does not have shuffle built in):
array.sort_by { rand }
For ruby 1.8.6 as sepp2k's example, but you still want use "shuffle" method.
class Array
def shuffle
sort_by { rand }
end
end
[1,2,3,4].shuffle #=> [2,4,3,1]
[1,2,3,4].shuffle #=> [4,2,1,3]
cheers
Code from the Backports Gem for just the Array for Ruby 1.8.6. Ruby 1.8.7 or higher is built in.
class Array
# Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
def shuffle
dup.shuffle!
end unless method_defined? :shuffle
# Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
def shuffle!
size.times do |i|
r = i + Kernel.rand(size - i)
self[i], self[r] = self[r], self[i]
end
self
end unless method_defined? :shuffle!
end
The Ruby Facets library of extensions has a Random module which provides useful methods including shuffle and shuffle! to a bunch of core classes including Array, Hash and String.
Just be careful if you're using Rails as I experienced some nasty clashes in the way its monkeypatching clashed with Rails'...

iterating over each character of a String in ruby 1.8.6 (each_char)

I am new to ruby and currently trying to operate on each character separately from a base String in ruby. I am using ruby 1.8.6 and would like to do something like:
"ABCDEFG".each_char do |i|
puts i
end
This produces a undefined method `each_char' error.
I was expecting to see a vertical output of:
A
B
C
D
..etc
Is the each_char method defined only for 1.9? I tried using the plain each method, but the block simply ouputs the entire string in one line. The only way I figure how to do this, which is rather inconvenient is to create an array of characters from the begining:
['A','B','C','D','...'].each do|i|
puts i
end
This outputs the desired:
A
B
C
..etc
Is there perhaps a way to achive this output using an unmodified string to begin with?
I think the Java equivalent is:
for (int i = 0; i < aString.length(); i++){
char currentChar = aString.charAt(i);
System.out.println(currentChar);
}
I have the same problem. I usually resort to String#split:
"ABCDEFG".split("").each do |i|
puts i
end
I guess you could also implement it yourself like this:
class String
def each_char
self.split("").each { |i| yield i }
end
end
Edit: yet another alternative is String#each_byte, available in Ruby 1.8.6, which returns the ASCII value of each char in an ASCII string:
"ABCDEFG".each_byte do |i|
puts i.chr # Fixnum#chr converts any number to the ASCII char it represents
end
Extending la_f0ka's comment, esp. if you also need the index position in your code, you should be able to do
s = 'ABCDEFG'
for pos in 0...s.length
puts s[pos].chr
end
The .chr is important as Ruby < 1.9 returns the code of the character at that position instead of a substring of one character at that position.
"ABCDEFG".chars.each do |char|
puts char
end
also
"ABCDEFG".each_char {|char| p char}
Ruby version >2.5.1
there is really a problem in 1.8.6.
and it's ok after this edition
in 1.8.6,you can add this:
requre 'jcode'
But now you can do much more:
a = "cruel world"
a.scan(/\w+/) #=> ["cruel", "world"]
a.scan(/.../) #=> ["cru", "el ", "wor"]
a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]]
a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]]
Returns an array of characters in str. This is a shorthand for str.each_char.to_a. If a block is given, which is a deprecated form, works the same as each_char.
from ruby-doc.org
also now you can do string.chars

How to chunk an array in Ruby

In Ruby 1.8.6, I have an array of, say, 100,000 user ids, each of which is an int. I want to perform a block of code on these user ids but I want to do it in chunks. For example, I want to process them 100 at a time. How can I easily achieve this as simply as possible?
I could do something like the following, but probably there's an easier way:
a = Array.new
userids.each { |userid|
a << userid
if a.length == 100
# Process chunk
a = Array.new
end
}
unless a.empty?
# Process chunk
end
Use each_slice:
require 'enumerator' # only needed in ruby 1.8.6 and before
userids.each_slice(100) do |a|
# do something with a
end
Rails has in_groups_of, which under the hood uses each_slice.
userids.in_groups_of(100){|group|
//process group
}

First order array difference in Ruby

What's the slickest, most Ruby-like way to do this?
[1, 3, 10, 5].diff
should produce
[2, 7, -5]
that is, an array of first order differences. I've come up with a solution which I'll add below, but it requires ruby 1.9 and isn't all that slick. what else is possible?
I like this functional style:
module Enumerable
def diff
each_cons(2).map {|pair| pair.reverse.reduce :-}
end
end
EDIT: I just realized that the reverse is totally unnecessary. If this were a functional language, I would have used pattern matching, but Ruby doesn't support pattern matching. It does, however, support destructuring bind, which is a good enough approximation for pattern matching in this case.
each_cons(2).map {|first, second| second - first}
No smiley, though.
I like how this sounds if you just read it out loud from left to right: "For each pair, apply the difference between the first and second elements of the pair." In fact, I normally don't like the name collect and prefer map instead, but in this case that reads even better:
each_cons(2).collect {|first, second| second - first}
"For each pair, collect the difference between its elements." Sounds almost like a definition of first order difference.
Yet another way..Seems the shortest so far:)
module Enumerable
def diff
self[1..-1].zip(self).map {|x| x[0]-x[1]}
end
end
The concept comes from functional programming, of course:
module Enumerable
def diff
self.inject([0]) { |r,x| r[-1] += x; r << -x } [1..-2]
end
end
[1,3,10,5].diff
Note that you don't need any separate intermediate variables here
Here's the fastest way I could find (faster than all the others suggested here as of this moment, in both 1.8 and 1.9):
module Enumerable
def diff
last=nil
map do |x|
r = last ? x - last : nil
last = x
r
end.compact
end
end
With this close runner-up:
module Enumerable
def diff
r = []
1.upto(size-1) {|i| r << self[i]-self[i-1]}
r
end
end
Of the others here, testr's self-described "feeble" attempt is the next fastest, but it's still slower than either of these.
And if speed is no object, here's my aesthetic favorite:
module Enumerable
def diff!
[-shift+first] + diff! rescue []
end
def diff
dup.diff!
end
end
But this is (for reasons I don't entirely understand) an order of magnitude slower than any other suggestion here!
Minor variation on Jörg W Mittag's:
module Enumerable
def diff
each_cons(2).map{|a,b| b-a}
end
end
# Attempt, requires ruby 1.9.
module Enumerable
def diff
each_cons(2).with_object([]){|x,array| array << x[1] - x[0]}
end
end
Example:
[1,3,10,5].diff
=> [2, 7, -5]
Another way to do it.
module Enumerable
def diff
result = []
each_with_index{ |x, i|
return result if (i == (self.length-1))
result << self[i+1] - x
}
end
end
My feeble attempt...
module Enumerable
def diff
na = []
self.each_index { |x| r << self[x]-self[x-1] if x > 0 }
na
end
end
p [1,3,10,5].diff #returned [2, 7, -5]

Resources