I'm blanking big time on this one. This is all i've got. Help all mighty Overflow gods!
ages = [23, 101, 7, 104, 11, 94, 100, 121, 101, 70, 44]
under_100 = Proc.new { |x| x < 100 }
Do as below
ages = [23, 101, 7, 104, 11, 94, 100, 121, 101, 70, 44]
under_100 = Proc.new { |x| x < 100 }
ages.select(&under_100) # => [23, 7, 11, 94, 70, 44]
ages.select { |x| x < 100 } # I would do this way or
ages.select(&100.method(:>)) # this way.
100.method(:>) created Method object(check this Object#method), same as the one you created as Proc.new { |x| x < 100 }. Now applying & to that proc/method object converting it to a block with #select method.
ages = [23, 101, 7, 104, 11, 94, 100, 121, 101, 70, 44]
under_100 = Proc.new { |x| x < 100 }
p under_100.call(201) #=> false
p under_100.call(23) #=> true
Map runs the proc on each element and returns the result:
p ages.map(&under_100) #=> [true, false, true, false, true, true, false, false, false, true, true]
Select goes through all elements and only returns the ones that evaluates to true:
p ages.select(&under_100) #=> [23, 7, 11, 94, 70, 44]
It could also be written like this:
result = []
ages.each{|age| result.push(age) if under_100.call(age)}
p result #=> [23, 7, 11, 94, 70, 44]
So that is why you do not need to use any if when using the select method of the Array.
without proc we can check it as
ages = [23, 101, 7, 104, 11, 94, 100, 121, 101, 70, 44]
ages.each do |x|
if x < 100;
puts "#{x} is less than 100";
end
end
Related
I'm trying to see if an index, say index 3, all has the same character. For example:
nested_array = [[47, 44, 71, 'x', 88],
[22, 69, 75, 'x', 73],
[83, 85, 97, 'x', 57],
[25, 31, 96, 'x', 51],
[75, 70, 54, 'x', 83]]
As we can see, index 3 has all x'x in it instead of numbers. I want to be able to verify if ALL of the indexes have an x, if so, program returns true. If all but 1 have x's it would return false.
I have now implemented this conditional statement as it iterates through each index looking for a value the size equal to 1. This seemed to do the trick.
if array.map {|zero| zero[0]}.uniq.size == 1
return true
elsif array.map {|one| one[1]}.uniq.size == 1
return true
elsif array.map {|two| two[2]}.uniq.size == 1
return true
elsif array.map {|three| three[3]}.uniq.size == 1
return true
elsif array.map {|four| four[4]}.uniq.size == 1
return true
else
return false
end
nested_array.empty? || nested_array.map {|row| row[3]}.uniq.one?
The special condition for empty arrays is necessary because they trivially fulfill any condition that is specified for each element, but the uniqueness test would not pick it up. Feel free to drop it if you will not in fact have an empty array, or the test should fail if the array is empty.
EDIT: Seems I misunderstood the question - try this as an alternative to your multi-if:
nested_array.transpose.any? { |column| column.uniq.one? }
"When you flip rows and columns, does any of the rows (that used to be columns) have only one unique element?"
(if you want true for [], again, prefix with nested_array.empty? || ...).
EDIT: Thanks to spickermann, replaced .size == 1 with .one?. It really does read better.
You did not specify that all elements of nested_array are necessarily of the same size, so I will offer a solution does not have that as a requirement:
nested_array = [[47, 44, 71, 'x', 88],
[75, 70, 54, 'x', 83, 85, 90],
[22, 69, 75, 'x', 73],
[83, 85, 97, 'x', 57],
[25, 31, 96, 'x', 51, 33]]
nested_array.first.zip(*nested_array[1..-1]).any? {|row| row.uniq.size==1}
#=> true
We have:
b = nested_array.first.zip(*nested_array[1..-1])
#=> [[47, 75, 22, 83, 25],
# [44, 70, 69, 85, 31],
# [71, 54, 75, 97, 96],
# ["x", "x", "x", "x", "x"],
# [88, 83, 73, 57, 51]]
b.any? { |row| row.uniq.size == 1 }
#=> true
Initally, I had:
nested_array.first.zip(*nested_array[1..-1]).any? {|row|
row[1..-1].all? { |e| e == row.first } }
rather than { |row| row.uniq.size==1 }. As #Amadan points out, the former should be a bit faster.
If the question is whether a specific element of b contains all the same values:
index = 3
a = nested_array.first.zip(*nested_array[1..-1])
(index >= a.size) ? false : a[index].uniq.size==1
#=> true
This question already has an answer here:
replacing an element in nested array ruby
(1 answer)
Closed 7 years ago.
Hello I have my following bingo code that marks X for numbers that get returned:
class BingoBoard
def initialize(board)
#bingo_board = board
end
def number_letter
#letter = ['B','I','N','G','O'].sample
#number = rand(1..100)
end
def checker
number_letter
#bingo_board.map! do |n|
if n.include?(#number) #cleaned up code from the initial solution.
n.map! { |x| x == #number ? 'X' : x}
else
n
end
end
end
end
My question is how do I change my code so that when I'm using the test code:
board = [[47, 44, 71, 8, 88],
[22, 69, 75, 65, 73],
[83, 85, 97, 89, 57],
[25, 31, 96, 68, 51],
[75, 70, 54, 80, 83]]
new_game = BingoBoard.new(board)
new_game.checker
It will appear neatly like a bingo board in irb.
Right now it looks like:
=>[[47, 44, 71, 8, 88], [22, 69, 75, 65, 73], ["X", 85, 97, 89, 57], [25, 31, 96, 68, 51], [75, 70, 54, 80, "X"]]
Append .map { |block| puts block.inspect } to the new_game.checker call.
I know I can get this easily:
array = [45, 89, 23, 11, 102, 95]
lower_than_50 = array.select{ |n| n<50}
greater_than_50 = array.select{ |n| !n<50}
But is there a method (or an elegant manner) to get this by only running select once?
[lower_than_50, greater_than_50] = array.split_boolean{ |n| n<50}
over, under_or_equal = [45, 89, 23, 11, 102, 95].partition{|x| x>50 }
Or simply:
result = array.partition{|x| x>50 }
p result #=> [[89, 102, 95], [45, 23, 11]]
if you rather want the result as one array with two sub-arrays.
Edit: As a bonus, here is how you would to it if you have more than two alternatives and want to split the numbers:
my_custom_grouping = -> x do
case x
when 1..50 then :small
when 51..100 then :large
else :unclassified
end
end
p [-1,2,40,70,120].group_by(&my_custom_grouping) #=> {:unclassified=>[-1, 120], :small=>[2, 40], :large=>[70]}
The answer above is spot on!
Here is a general solution for more than two partitions (for example: <20, <50, >=50):
arr = [45, 89, 23, 11, 102, 95]
arr.group_by { |i| i < 20 ? 'a' : i < 50 ? 'b' : 'c' }.sort.map(&:last)
=> [[11], [45, 23], [89, 102, 95]]
This can be very useful if you're grouping by chunks (or any mathematically computable index such as modulo):
arr.group_by { |i| i / 50 }.sort.map(&:last)
=> [[45, 23, 11], [89, 95], [102]]
I want to write a program that splits an array into two arrays, where any element in one array is smaller than any element in the other array.
The input that I have is:
a = [6, 45, 23, 65, 17, 48, 97, 32, 18, 9, 88]
And I'd like output like this:
[6, 23, 17, 18 , 9] < [45, 65, 48, 97, 32, 88]
I've tried:
i = 0
max = 0
while i < a.size
if a[i] > max
max = a[i]
end
i+=1
end
puts "this is the larger array: " + max.to_s
Which is completely off. As I am new to this, any help is appreciated.
small, large = a.sort!.shift(a.size/2) ,a
p small, large
#=> [6, 9, 17, 18, 23]
#=> [32, 45, 48, 65, 88, 97]
Try this:
newarray = a.sort.each_slice((a.size/2.0).round).to_a
It will give you an array containing your split array:
newarray = [[6,9,17,18,23,32],[45,48,65,88,97]]
In this case, if you have an odd number of elements in your array, the first array returned will always have the extra element. You can also save the arrays separately if you would like, but this way you can call each of the halves with newarray[0] and newarray[1]. If you want to split them simply add:
b = newarray[0]
c = newarray[1]
Don't use a while loop - sort the array and then split it in two
a.sort
a.in_groups_of( a.size/2)
a.sort.each_slice( a.size/2) probably does the trick without rails.
a = [6, 45, 23, 65, 17, 48, 97, 32, 18, 9, 88]
a = a.sort
print a.shift(a.count/2), " < " , a
#=> [6, 9, 17, 18, 23] < [32, 45, 48, 65, 88, 97]
Another variation
a = [6, 45, 23, 65, 17, 48, 97, 32, 18, 9, 88]
a = a.sort
print a.values_at(0..a.count/2), " < ", a.values_at((a.count/2)+1 .. -1)
#=> [6, 9, 17, 18, 23] < [32, 45, 48, 65, 88, 97]
Assuming you want to preserve order, as in your example:
def split_it(a,n)
f = a.select {|e| e <= n}
[f, a-f]
end
a = [6, 45, 23, 65, 17, 48, 97, 32, 18, 9, 88]
f, l = split_it(a,23)
puts "#{f} < #{l}" # => [6, 23, 17, 18, 9] < [45, 65, 48, 97, 32, 88]
If you want to preserve order and have the first subarray contain nbr elements, add this:
def split_nbr(a, nbr)
n = 1
loop do
return [] if n > a.max
b = split_it(a,n)
return b if b.first.size == nbr
n += 1
end
end
f, l = split_nbr(a,3)
puts "#{f} < #{l}" # => [6, 17, 9] < [45, 23, 65, 48, 97, 32, 18, 88]
Is there any cool way in Ruby to create an array with 1 to 100 with only odd entries (1, 3 etc). I now have a loop for this but that is obviously not a cool way to do it! Any suggestions?
My current code:
def create_1_to_100_odd_array
array = [1]
i = 3
while i < 100
array.push i
i += 2
end
array
end
Thanks in advance
The Range class comes with a very cool feature for that purpose:
1.9.3-p286 :005 > (1..10).step(2).to_a
=> [1, 3, 5, 7, 9]
May not be efficient, but a short piece of code:
(1..100).select(&:odd?)
# => [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]
Just toying...
(0...50).map(&:object_id)
#or
1.step(100,2).to_a
Since you need a function, then:
def odd_to(n)
(1..n).step(2).to_a
end
Not very effective solution, but quite elegant:
(1..100).select {|a| a%2 != 0}
You can do it as a one-liner when you instantiate the array:
def create_array_of_odds_to(n)
Array.new((n + 1) / 2) {|i| 2 * i + 1}
end
create_array_of_odds_to 10 # => [1, 3, 5, 7, 9]