Is this a bug in the Array.fill method in Ruby? [duplicate] - arrays

This question already has an answer here:
Arrays misbehaving
(1 answer)
Closed 6 years ago.
Should this be the case i.e. I am misunderstanding, or is it a bug?
a = Array.new(3, Array.new(3))
a[1].fill('g')
=> [["g", "g", "g"], ["g", "g", "g"], ["g", "g", "g"]]
should it not result in:
=> [[nil, nil, nil], ["g", "g", "g"], [nil, nil, nil]]

Array.new(3, Array.new(3)) returns an array which contains the same array three times (in other words: the expression Array.new(3) is evaluated exactly once and no copies are made).
What you probably want is Array.new(3) { Array.new(3) }, which evaluates Array.new(3) three times and thus gives you an array of three independent arrays.

It is correct, Array.new(array) returns a new array created with size copies of obj (that is, size references to the same obj)

Related

Sort 2 linked arrays in Swift? [duplicate]

This question already has answers here:
In Swift how can I sort one array based on another array?
(4 answers)
Closed 4 years ago.
I want to sort one array and "mirror" order changes to another array of the same dimension.
The question is similar to this one but for Swift language:
Better way to sort 2 "linked" arrays?
Example:
let arr1 = ["a", "b", "c", "d", "e"]
let arr2 = [1, 5, 9, 2, 3]
... //sort
//result == ["a", "d", "e", "b", c"]
Approximate solution I know:
for i in stride(from 0, to: arr2.count - 1, by: 1) {
for j in stride(from i + 1, to: arr2.count, by: 1) {
if arr2[i] > arr2[j] {
...//swap arr2[i] and arr2[j]
...//swap arr1[i] and arr1[j]
}
}
}
But they added a lot of additional possibilities for advanced working with arrays in Swift. So is it possible to simplify this solution with inner Swift features?
Note: arr1 and arr2 are given as separate arrays.
EDITED
Yes. You found the similar questions but their titles are awful and don't reflect the answers their authors need. In other words if you delete/close my question the people may continue to ask it again because it is impossible to find something with existing titles!
zip the arrays together
sort the new array by array 2
map the array to array 1
let arr1 = ["a", "b", "c", "d", "e"]
let arr2 = [1, 5, 9, 2, 3]
let result = zip(arr1, arr2) // [("a", 1), ("b", 5), ("c", 9), ("d", 2), ("e", 3)]
.sorted(by: {$0.1 < $1.1}) // [("a", 1), ("d", 2), ("e", 3), ("b", 5), ("c", 9)]
.map{ $0.0 } // ["a", "d", "e", "b", "c"]

How do I split an array into smaller arrays bsaed on a condition?

Ruby 2.4. I have an array of strings
2.4.0 :007 > arr = ["a", "b", "g", "e", "f", "i"]
=> ["a", "b", "g", "e", "f", "h", "i"]
How do I split my array into smaller arrays based on a condition? I have a function -- "contains_vowel," which returns true if a string contains "a", "e", "i", "o", or "u". How would I take an array of strings and split it into smaller arrays, using a divider function of "contains_vowel"? That is, for the above, the resulting array of smaller arrays would be
[["a"], ["b", "g"], ["e"], ["f", "h"], ["i"]]
If an element of the larger array satisfies the condition, it would become an array of one element.
arr = ["a", "b", "g", "e", "f", "i"]
r = /[aeiou]/
arr.slice_when { |a,b| a.match?(r) ^ b.match?(r) }.to_a
=> [["a"], ["b", "g"], ["e"], ["f"], ["i"]]
String#match? made its debut in Ruby v2.4. For earlier versions you could use (for example) !!(b =~ r), where !! converts a truthy/falsy value to true/false. That converstion is needed because the XOR operator ^ serves double-duty: it's a logical XOR when a and b in a^b are true, false or nil, and a bit-wise XOR when the operands are integers, such as 2^6 #=> 4 (2.to_s(2) #=> "10"; 6.to_s(2) #=> "110"; 4.to_s(2) #=> "100").
One more way to skin a cat
def contains_vowel(v)
v.count("aeiou") > 0
end
def split_by_substring_with_vowels(arr)
arr.chunk_while do |before,after|
!contains_vowel(before) & !contains_vowel(after)
end.to_a
end
split_by_substring_with_vowels(arr)
#=> [["a"], ["b", "g"], ["e"], ["f", "h"], ["i"]]
What it does:
passes each consecutive 2 elements
splits when either of them contain vowels
Example with your other Array
arr = ["1)", "dwr", "lyn,", "18,", "bbe"]
split_by_substring_with_vowels(arr)
#=> [["1)", "dwr", "lyn,", "18,"], ["bbe"]]
Further example: (if you want vowel containing elements in succession to stay in the same group)
def split_by_substring_with_vowels(arr)
arr.chunk_while do |before,after|
v_before,v_after = contains_vowel(before),contains_vowel(after)
(!v_before & !v_after) ^ (v_before & v_after)
end.to_a
end
arr = ["1)", "dwr", "lyn,", "18,", "bbe", "re", "rr", "aa", "ee"]
split_by_substring_with_vowels(arr)
#=> [["1)", "dwr", "lyn,", "18,"], ["bbe", "re"], ["rr"], ["aa", "ee"]]
This checks if before and after are both not vowels Or if they both are vowels
I might use chunk which splits an array everytime the value of its block changes. Chunk returns a list of [block_value, [elements]] pairs, I used .map(&:last) to only get the sub-lists of elements.
arr = ["a", "b", "g", "e", "f", "h", "i"]
def vowel?(x); %w(a e i o u).include?(x); end
arr.chunk{|x| vowel?(x)}.map(&:last)
=> [["a"], ["b", "g"], ["e"], ["f", "h"], ["i"]]
contains_vowel = ->(str) { !(str.split('') & %w|a e i o u|).empty? }
_, result = ["a", "b", "g", "e", "f", "h", "i"].
each_with_object([false, []]) do |e, acc|
cv, acc[0] = acc[0], contains_vowel.(e)
cv ^ acc.first ? acc.last << [e] : (acc.last[-1] ||= []) << e
end
result
#⇒ [["a"], ["b", "g"], ["e"], ["f", "h"], ["i"]]
What we do here:
contains_vowel is a lambda to check whether the string contains a vowel or not.
we reduce the input array, collecting the last value (contained the previously handled string the vowel or not,) and the result.
cv ^ acc.first checks whether it was a flip-flop of vowel on the last step.
whether is was, we append a new array to the result
whether is was not, we append the string to the last array in the result.

Is there a Ruby Array method that returns two sub-arrays: one of specified size and another of the remaining contents?

I need to render the contents of the first 5 elements of an array and display "And X more" on a web page. Is there a built-in method on Array (or Enumerable) that easily separates one array into two sub-arrays: the first consisting of up to a fixed size and the second consisting of the array remainder?
I'm looking for one simple method call that will do this for me. Most of the methods that I looked at (like Enumerable#partition) use a logical condition to divide the array and don't supply the index to the block.
I just wrote the following code to do what I want. Please save me from myself and direct me to a method that already does it.
class Array
def bifurcate(size=length)
if size < 0
raise ArgumentError, "attempt to bifurcate using negative size"
end
remainder_size = length - size
if remainder_size < 0
remainder_size = 0
end
[
first(size),
last(remainder_size)
]
end
end
('a'..'g').to_a.bifurcate(2)
# => [["a", "b"], ["c", "d", "e", "f", "g"]]
('a'..'g').to_a.bifurcate(20)
# => [["a", "b", "c", "d", "e", "f", "g"], []]
('a'..'g').to_a.bifurcate()
# => [["a", "b", "c", "d", "e", "f", "g"], []]
('a'..'g').to_a.bifurcate(0)
# [[], ["a", "b", "c", "d", "e", "f", "g"]]
('a'..'g').to_a.bifurcate(-1)
# ArgumentError: attempt to bifurcate using negative size
Also, let me qualify that I want one simple method call to do what I want. Also consider that the starting array may contain duplicate values and this method needs to respect the original array and return duplicates.
You can use Enumerable#partition along with Enumerator#with_index method, as shown below:
size = 2
(1..6).partition.with_index { |_,i| i < size }
#=> [[1, 2], [3, 4, 5, 6]]
Alternatively, if your input array can be mutated, then, following will also do the trick
[array.shift(size), array]
[array.take(3), array.drop(3)]
# [["a", "b", "c"], ["d", "e", "f", "g"]]
Hope it helps :)
Use Array#[]:
[arr[0,size_of_first], arr[size_of_first..-1] || []]

Ruby. How to split a string element inside an array?

I have an array of arr=["abcd"]
Q1. Is there a simpler way to split the 'abcd' into arr=["a","b","c","d"] than the following:
arr=["abcd"]
arr_mod=[]
x=0
while x < arr[0].size
arr_mod << arr[0][x]
x +=1
end
puts "==>#{arr_mod}"
arr.split('') will not work.
Q2. Is there a method to convert arr=["abcd"] to the string of "abcd"?
arr.first.split('')
#=> ["a", "b", "c", "d"]
arr.first
#=> "abcd"
Q1:
This would give you some flexibility in case you ever needed a way to iterate over an array of more than one element:
arr = ['abcd']
arr = arr[0].split("")
#=> ["a", "b", "c", "d"]
Q2:
arr = ['abcd']
arr = arr[0]
#=> "abcd"
Simplest way is to do
arr.join("").chars
This turns the arr into one big string, then turns that string into an array of characters.
For your second question, just do arr.join(""), which will turn all the strings into the array into one big string.
For more information, check out Array#join and String#chars for more detail.
Q1:
arr.map(&:chars).flatten
#=> ["a", "b", "c", "d"]
Q2:
arr = arr[0]
#=> "abcd"
This is one way:
arr.join.split('') #=> ["a", "b", "c", "d"]

removing array brackets

I think its' silly question lol
I have below array
[['a','b','c'],['d','e','f']]
and want that array to be
['a','b','c'],['d','e','f']
which means i want to remove the first bracket.
Does that make sense?
Thanks in adv.
no, this doesn't make sense really, because ['a','b','c'],['d','e','f'] in this notation are two separate objects/arrays not inside any other data structure...
you could do an assignment, like :
a,b = [['a','b','c'],['d','e','f']]
and then
> a
=> ["a", "b", "c"]
> b
=> ["d", "e", "f"]
or better just iterate over the outer array (because you don't know how many elements it has):
input = [['a','b','c'],['d','e','f']]
input.each do |x|
puts "element #{x.inspect}"
end
=>
element ["a", "b", "c"]
element ["d", "e", "f"]
It doesn’t make sense. Do you mean a string manipulation?
irb(main):001:0> s = "[['a','b','c'],['d','e','f']]"
=> "[['a','b','c'],['d','e','f']]"
irb(main):002:0> s[1...-1]
=> "['a','b','c'],['d','e','f']"
Or, do you want to flatten an array?
irb(main):003:0> [['a','b','c'],['d','e','f']].flatten
=> ["a", "b", "c", "d", "e", "f"]

Resources