I need to parse and display solr facets which are returned in either JSON or Ruby formar:
Collections: [ "a", 1, "b", 2, "c", 3, "d", 4, ... ]
into
{"a"=>1, "b"=>2, "c"=>3, "d"=>4}
What is the cleanest way?
EDIT: Well now that we know what you actually want, a hash ...
collections = ["a", 1, "b", 2, "c", 3, "d", 4]
Hash[*collections]
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
Original answer: I may not understand your goal but...
collections = ["a", 1, "b", 2, "c", 3, "d", 4]
collections.each_slice(2).map{ |(x, y)| "#{x} - #{y}" }
# => ["a - 1", "b - 2", "c - 3", "d - 4"]
What i see you want to do is maybe a hash ? {a => "1", b => "2"} ??
If so, read below:
collections = [ "a", 1, "b", 2, "c", 3, "d", 4]
result = Hash[*collections.flatten]
result prints {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
Related
I've got an array in the following form:
[["First", ["a", "b", "c"]], ["Second", ["d", "e"]], ["Third", ["g", "h", "i"]]]
Is there a way to somehow display this information on a Rails template using iterators? I need something like this:
First - a, b, c
Second - d, e,
Third - g, h, i.
Or this is impossible and I should modify the initial array form?
Thanks in advance.
Without modifing the main array you could try with each_with_index inside each for the main array of arrays, then checking for the first value you can skip it and get the array of letters:
array = [["First", ["a", "b", "c"]], ["Second", ["d", "e"]], ["Third", ["g", "h", "i"]]]
array.each do |main|
main.each_with_index do |value, index|
next if index.zero?
p value
end
end
# => ["a", "b", "c"]
# ["d", "e"]
# ["g", "h", "i"]
Or if you want to access it as a hash it'd be easier:
array = [["First", ["a", "b", "c"]], ["Second", ["d", "e"]], ["Third", ["g", "h", "i"]]]
array.to_h.each do |_, value|
p value
end
# => ["a", "b", "c"]
# ["d", "e"]
# ["g", "h", "i"]
This question already has answers here:
Why are exclamation marks used in Ruby methods?
(12 answers)
Closed 7 years ago.
a = [1,2,3]
a.uniq! # nil
a.uniq # [1,2,3]
Why a.uniq! is not [1,2,3] ?
Let me know the reason. Thank you!
You need to read the Ruby documentation.
The uniq method returns a new array by removing duplicate values in self. If no duplicates are found, the same array value is returned.
a = [ "a", "a", "b", "b", "c" ]
a.uniq # => ["a", "b", "c"]
b = [ "a", "b", "c" ]
b.uniq # => ["a", "b", "c"]
The uniq! method removes duplicate elements from self and returns nil if no changes are made (that is, no duplicates are found).
a = [ "a", "a", "b", "b", "c" ]
a.uniq! # => ["a", "b", "c"]
b = [ "a", "b", "c" ]
b.uniq! # => nil
most of the methods ending with bang (!) change the variable, while those without it just return the altered variable.
So, if you have something like this:
a = [1, 1, 2, 3]
a.uniq will return [1, 2, 3], but wont alter a, while a! will alter a to be equal to [1, 2, 3]
[1] pry(main)> a = [1,1,2,3]
=> [1, 1, 2, 3]
[2] pry(main)> a.uniq
=> [1, 2, 3]
[3] pry(main)> a
=> [1, 1, 2, 3]
[4] pry(main)> a.uniq!
=> [1, 2, 3]
[5] pry(main)> a
=> [1, 2, 3]
[6] pry(main)> a.uniq!
=> nil
[7] pry(main)> a
=> [1, 2, 3]
Suppose, I have an array of five elements ['a','b','c','d','e']. I want combinations of four elements but I want that 'a' and 'b' not be together in any of combinations. How would I do that?
Expected result should be
['a', 'c', 'd', 'e']
['b', 'c', 'd', 'e']
Please write a more generalize solution.I am using ruby's combination method.I here just write an example.It may be possible that the combination number may vary(like there may be a array of 9 with size of 7 combinations) and also It may needed that I want two elements say a and e and d and f should not be together in any of combination.I know it bit confusing please let me know if I need to explain.Would really appreciate any help.
['a','b','c','d','e'].permutation(4).reject do |e|
e.include?('a') && e.include?('b')
end
Or, if you do not care about element order (credits to #mark-thomas,) use Array#combination:
['a','b','c','d','e'].combination(4).reject do |e|
e.include?('a') && e.include?('b')
end
#⇒ [["a", "c", "d", "e"], ["b", "c", "d", "e"]]
Please note, this approach is eager to resources. I’dn’t recommend to use it on big arrays.
I think you are looking for something like that:
def combine(array, should_not_be_together, size)
aux = []
add_together = true
while aux.size < size
random = Random.rand(2)
if random == 1
aux << array.sample
elsif add_together
aux << should_not_be_together.sample
add_together = false
end
aux.uniq!
end
aux
end
array = ['c', 'd', 'e']
should_not_be_together = ['a', 'b']
size = 4
combine(array, should_not_be_together, size)
Results:
# => ["c", "a", "d", "e"]
# => ["e", "b", "c", "d"]
# => ["e", "a", "c", "d"]
# => ["c", "d", "b", "e"]
# => ["d", "b", "e", "c"]
# => ["a", "c", "e", "d"]
# => ["c", "b", "d", "e"]
# => ["c", "a", "e", "d"]
I have an array of strings. I'm wanting to change the name of these duplicate strings to append a numerical value to make them unique like so...
Original Array
a, a, A, b, c, D, d
Corrected Array
a, a1, A2, b, c, D, d1
I've gotten close to this with the following code; however, if the strings are a different case structure then they aren't currently considered duplicates with this code snippet. I would like them to be considered duplicates, but yet not change their case in the results array.
duplicate_counter = 1
duplicates = Array.new
duplicates = file_columns.select{ |e| file_columns.count(e) > 1 } # get duplicate column names
duplicates.each{ |x| file_columns.delete(x) }
duplicates.sort!
duplicates.each_with_index do |d, i|
if i > 0
if d == duplicates[i-1]
d = d.strip + duplicate_count.to_s
duplicate_count += 1
else
duplicate_count = 1
end
end
# Add back the column names, but with the appended numerical counts to make them unique
file_columns.push(d)
end
You are over thinking it considerably. I'm sure there are better ways to do this as well, but it gets the job done.
a = ['a', 'a', 'A', 'b', 'c', 'D', 'd']
letters = Hash.new(-1)
a.map do |letter|
l = letter.downcase
letters[l] += 1
if (letters[l] > 0)
"#{letter}#{letters[l]}"
else
"#{letter}"
end
end
Here's a way to do it if letters independent of case are not necessarily grouped. For example, it will convert this array:
arr = %w{ a D a A b c D a d }
#=> ["a", "D", "a", "A", "b", "c", "D", "a", "d"]
to:
["a", "D", "a1", "A2", "b", "c", "D1", "a3", "d2"]
Code
def convert(arr)
arr.each_with_index
.group_by { |c,_| c.downcase }
.values
.flat_map { |c|
c.map
.with_index { |(f,l),i| [i > 0 ? f<<i.to_s : f, l] } }
.sort_by(&:last)
.map(&:first)
end
Example
For arr above:
convert(arr)
#=> ["a", "D", "a1", "A2", "b", "c", "D1", "a3", "d2"]
Explanation
Dear reader, if you are new to Ruby, this may look impossibly complex. If you break it down into steps, however, it's not that bad. After you gain experience and become familiar with commonly-used methods, it will come quite naturally. Here I've used the following methods, chained together so that the return value of each becomes the receiver of the next:
Enumerable#each_with_index
Enumerable#group_by
Hash#values
Enumerable#flat_map
Enumerable#sort_by
Enumerable#first
Here's what's happening.
enum = arr.each_with_index
#=> #<Enumerator: ["a", "D", "a", "A", "b", "c",
# "D", "a", "d"]:each_with_index>
h = enum.group_by { |c,_| c.downcase }
#=> {"a"=>[["a", 0], ["a", 2], ["A", 3], ["a", 7]],
# "d"=>[["D", 1], ["D", 6], ["d", 8]],
# "b"=>[["b", 4]],
# "c"=>[["c", 5]]}
a = h.values
#=> [[["a", 0], ["a", 2], ["A", 3], ["a", 7]],
# [["D", 1], ["D", 6], ["d", 8]],
# [["b", 4]],
# [["c", 5]]]
b = a.flat_map { |c| c.map.with_index { |(f,l),i| [i > 0 ? f<<i.to_s : f, l] } }
#=> [["a", 0], ["a1", 2], ["A2", 3], ["a3", 7], ["D", 1],
# ["D1", 6], ["d2", 8], ["b", 4], ["c", 5]]
c = b.sort_by(&:last)
#=> [["a", 0], ["D", 1], ["a1", 2], ["A2", 3], ["b", 4],
# ["c", 5], ["D1", 6], ["a3", 7], ["d2", 8]]
c.map(&:first)
#=> ["a", "D", "a1", "A2", "b", "c", "D1", "a3", "d2"]
I have an array which contains numbers and alphabets something like:
newArray = ["1 a", "1 b" ,"2 c", "2 a"]
I would like to sort them in a way that the output is expected as follows:
newArray = ["2 a", "2 c" ,"1 a", "1 b"]
What I want to do is sort the numbers in descending order and if the numbers are same, then sort alphabetically
Can I implement a comparison function in sort_by or is there a way to do that using ruby sort
First you should use a better representation of your input. You can parse your existing array for example like this:
arr = newArray.map { |s| x,y = s.split; [x.to_i, y] }
# => [[1, "a"], [1, "b"], [2, "c"], [2, "a"]]
Then we can sort as we wish using sort_by:
arr.sort_by { |x,y| [-x, y] }
# => [[2, "a"], [2, "c"], [1, "a"], [1, "b"]]
Similar to #NiklasB. 's answer above (copied his sort_by)
arr.map(&:split).sort_by { |x,y| [-x.to_i, y] }
=> [["2", "a"], ["2", "c"], ["1", "a"], ["1", "b"]]
In a less elegant way, you can do that
arr.sort! do |p1, p2|
num1, str1 = p1.split(' ')
num2, str2 = p2.split(' ')
if (num1 != num2)
p2 <=> p1
else
p1 <=> p2
end
end
$stdout.puts arr