Reputation: 2854
I'm programming in Ruby.
Given that I have the following 2D array:
list = [
["T1", "Cat 1"],
["T2", "Cat 2"],
["T3", "Cat 3"],
["T4", "Cat 4"],
["T5", "Cat 1"],
["T6", "Cat 2"],
["T7", "Cat 3"],
["T8", "Cat 4"],
["T9", "Cat 1"],
["T10", "Cat 2"],
["T11", "Cat 3"],
["T12", "Cat 4"],
]
I also have a list of categories:
cat = ["Cat 1", "Cat 2", "Cat 3", "Cat 4"]
cat_count = cat.count
I also have the method bold
, which formats text to be bold, for simplicity here I am going to use the method below:
def bold(text)
'b_' << text
end
I would like to format each set of categories, in an alternating fashion. So the first set would be bold, and then the second set not, the third set bold, the fourth set not etc.
In this case I would get out the following formatted output: T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12
I expect the following ruby output:
["b_T1", "Cat 1"]
["b_T2", "Cat 2"]
["b_T3", "Cat 3"]
["b_T4", "Cat 4"]
["T5", "Cat 1"]
["T6", "Cat 2"]
["T7", "Cat 3"]
["T8", "Cat 4"]
["b_T9", "Cat 1"]
["b_T10", "Cat 2"]
["b_T11", "Cat 3"]
["b_T12", "Cat 4"]
I have the following code at the moment, which does not look very Rubyist at all. Please help me improve this code.
cat_increment = 0
switch = 1
list.map do |l|
cat_increment+=1
entry = switch ? [bold(l.first), l.second] : l
if cat_increment == cat_count
switch = switch ? nil : 1
cat_increment = 0
end
entry
end
Upvotes: 0
Views: 83
Reputation: 110685
enum = [*["b_"]*cat.size, *[""]*cat.size].cycle
#=> #<Enumerator: ["b_", "b_", "b_", "b_", "", "", "", ""]:cycle>
list.map { |t,c| [enum.next+t, c] }
#=> [["b_T1", "Cat 1"], ["b_T2", "Cat 2"], ["b_T3", "Cat 3"], ["b_T4", "Cat 4"],
# ["T5", "Cat 1"], ["T6", "Cat 2"], ["T7", "Cat 3"], ["T8", "Cat 4"],
# ["b_T9", "Cat 1"], ["b_T10", "Cat 2"], ["b_T11", "Cat 3"], ["b_T12", "Cat 4"]]
Array#cycle is used to convert the array ["b_", "b_", "b_", "b_", "", "", "", ""]
to an endlessly repeating enumerator.
It is then simply a matter of mapping each element of list
to a new value in which the "T" string is prepended with the next element of enum
("b_"
or ""
).
I have chosen to use this enumerator to add "T" prefixes that alternate with each group of cat.size
elements, but the more conventional way is to use indices:
list.map.with_index { |(t,c),i| [(i/4).even? ? "b_"+t : "t", c] }
#=> [["b_T1", "Cat 1"], ["b_T2", "Cat 2"], ["b_T3", "Cat 3"], ["b_T4", "Cat 4"],
# ["T5", "Cat 1"], ["T6", "Cat 2"], ["T7", "Cat 3"], ["T8", "Cat 4"],
# ["b_T9", "Cat 1"], ["b_T10", "Cat 2"], ["b_T11", "Cat 3"], ["b_T12", "Cat 4"]]
With Ruby 2.3.1 you will be able to write:
list.each_with_index { |(t,_),i| print "#{ (i/4).even? ? t.boldify : t } " }
T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12
Upvotes: 1
Reputation: 2669
You could use with_index
, array decomposition and some math:
list.map.with_index do |(title, category), index|
if index % (2 * cat_count) < cat_count
[bold(title), category]
else
[title, category]
end
end
Upvotes: 3