How do i find if element is not in a ruby array? - ruby

Ok so i have this array
array
=> [1620, 3093]
and I have a integer
num
=> 1620
is there an easy way to see if there is another number in the array that is not num
so for example
is there another number in the array that doesnt match num. So for the above example i would return true but if array was [1620, 1620] then i would return false

arr.any?{|x| x != num }
The above should work fine, is readable and efficient too!

array.reject{ |a| a == num }.size > 0

array.select{|array_num| array_num != num}.length > 0
EDIT: or even cleaner:
(array - [num]).empty?

Join the sorted array with a separator and find if there is a match with 2 adjacent numbers.
array.sort.join(",").include?("#{num},#{num}")

Related

How can I use conditional assignment in ruby

I want to set the value of a equal to the index found unless that index is zero, in which case I want to set it to some number minus that value. I am wondering if it is possible to perform this action (taken from python) in Ruby:
a='/-123456789X'.find(y)or 99-x
Does anyone know of a good way to do this?
Try this one. Given x and y
a = "/-123456789X".index(y) || 99 - x
In python string.find(other) will return the index of other or -1 if other does not exist in string.
In ruby string.index(other) will return the index of other or nil if other does not exist in string.
"Truthy" and "Falsey" values:
ruby acknowledges nil as "falsey" and 0 as "truthy"; but
python acknowledges 0 as "falsey" and -1 as "truthy"
So your current python code has 3 possible return values:
-1 (non-existent sub-string)
99 - x (existent sub-string starting with '/')
n (index of existent sub-string that does not start with '/')
In order to achieve an equivalent result in ruby your code could look like this:
str = '/-123456789X'
a = if y.start_with?('/') && str.index(y)
99 - x
else
str.index(y) || -1
end
Other alternatives include:
# Ruby >= 2.5 using `String#match?
str.match?(/\A#{y}/) ? 99 - x : str.index(y) || -1
That being said your actual request "I want to set the value of a equal to the index found unless that index is zero, in which case I want to set it to some number minus that value" seems a little different and I am not sure if this means that x is "that value" and what x should represent in that case.
Should x be the begining index?
Should x be the ending index?

Array inside Hash - Some questions

I have this code:
a = {}
a["First"] = [true, false]
How can I read "false"? Tried: ["First"][2] but output is blank;
How can I check if ["Second"] exist or if its array length > 0? Tried if a["Second"] is nil end or if a["Second"].value.length>0 but both seems incorrect;
How can I push/pop a new "true" value inside the existing a["First"]'s array?
How can I delete from a the ["First"] index? (such as a.pop["First"])
Can you help me?
Ruby arrays are 0 based so the elements are 0 and 1; there is not 2. Use: a["First"][1]
a["Second"].nil? is true if there is no "Second" element of the hash. Use size to get array length, so: a["Second"].size once you know "Second" exists.
Use: a["First"].push true
Use: a["First"].pop
(a["First"] gets you to the array; a alone is the hash made up of the two arrays.)
combining all comments:
if you want to read false, you should do a["First"][1] not a["First"][2]
a["First"].push('else') to push value
a.delete("First")

Ruby: iterate subarray and count items; write back count into element

I have an XML-File with <pb n="4-DIGIT-NUMBER" ... />. The number being in some cases identical, so I'd like to disambiguate, coming so far, but now problems with counting (do I have the right approach? => 3))
1) Reading the all numbers into an Array, yielding a very long list with:
Dir.chdir("./Tustep/luxneu")
sammel = []
open("lp42tags.txt").each do |x|
if x =~ /<pb n="(\d\d\d\d)/
sammel << $1
end
end
2) Finding the numbers repeating and put them into subarrays
dupl_groups = sammel.select{|i| sammel.grep(i).size > 1}.group_by{|x| x}.values
p dupl_groups
# (much shorter example)=> [["0119", "0119"], ["0147", "0147"], ["0156", "0156", "0156"]]
3) Now I thought I could somehow count the elements of each subarray and put them back into (or into a copy..). I want e.g. [["0119:1", "0119:2"], [...], ["0156:1", "0156:2", "0156:3"], maybe like this (but only got hilarious loops with almost endless number computations... :/)
dupl_counted = []
dupl_groups.each do |outer|
count = 1
dupl_groups do |inner|
#puts inner.inspect
inner_new = inner.to_s.sub(/(.+)/, "\\1:#{count}")
dupl_counted << inner_new
count += count
end
end
Seriously flawed..? Maybe something instead using "each_with_index"? Also I need the groups for counting in meaningful chunks (slice 3 or so is unacceptable, because there are number-repetitions ranging from 2-6). If I could split the array in its subarrays yielding them all as normal arrays, would that be good?
Thanks in advance!
René T.
This should be just a nested application of map - once to the outer group, and then to each element within:
dupl_groups.map do |gp|
gp.map.with_index {|el, ix| el + ":#{ix+1}"}
end
# => [["0119:1", "0119:2"], ["0147:1", "0147:2"], ["0156:1", "0156:2", "0156:3"]]

Compare multiple variables with a value in a single expression

I have two variables a and b. I want to compare both a and b to a value, say 10.
I can do it like this:
10 == a && 10 == b
But, I was wondering if there is any way to write it in a single expression? (E.g. like a == b == 10)
[a,b,3].all? {|x| x==10}
but in this case
[].all? {|x| x==10}
will also return true
Updated, after comment from aztaroth:
[a,b].uniq == [10]

Using a block to find values matching criteria

To me this makes perfect sense:
triple = dice.collect {|value| if (dice.count(value) >= 3)} ---> Syntax error
OR
triple = dice.collect {|value| dice.count(value) >= 3} ----> Array of true/false
I want the value of the number, not the true or falsity of dice.count(). I know there must be a simple way of doing this.
It sounds like you want Array#select, not Array#collect (also known as Array#map).
collect/map will take each value and put the results of your block into an array. This is why you're seeing an array of true/false.
select will take each value, and return it as a member of an array if the block evaluates to true:
triple = dice.select{ |value| dice.count(value) >= 3 }
Your block needs to return whatever it is you want in the final array.
triple = dice.collect {|value|
if dice.count(value) >= 3
dice.count(value)
end
}
Note that this will return nil for elements < 3 (though you can add an else to return 0 or something). If you only want elements that match your query, you'll need to use dice.select()
As for your first code snippet,
triple = dice.collect {|value| THE_CODE_BLOCK_STARTS_HERE }
Thus, if (dice.count(value) >= 3) is an incomplete if statement. That's why you get syntax error.

Resources