Reputation: 1332
Given:
data = [
{"id"=>nil, "votable_id"=>1150, "user_ids"=>"1120,1119,1118,1117,1116,1115,1114,1113,1112,1111,1110,1109,1108,1107"},
{"id"=>nil, "votable_id"=>1151, "user_ids"=>"1120,1119,1118,1117,1116,1115,1114,1113,1112,1111,1110,1109,1108,1107"}
]
I wish to return an array of all unique representations of integers in the strings g["user_ids"]
, taken over all hashes g
that are elements of data
; namely,
["1120", "1119", "1118", "1117", "1116", "1115", "1114",
"1113", "1112", "1111", "1110", "1109", "1108", "1107"]
Upvotes: 0
Views: 854
Reputation: 31467
To get the unique ids:
unique_ids = data.flat_map { |d| d['user_ids'].split(',') }.uniq
Enumerable#flat_map
walks through the Array and concatenate
the results provided in the code block.String#split
divides the string by the delimiter
into an Array.Array#uniq
removes the duplicates.Upvotes: 2
Reputation: 110675
data.reduce('') { |s,h| s + h['user_ids'] + ',' }.scan(/\d+/).uniq
#=> ["1120", "1119", "1118", "1117", "1116", "1115", "1114", "1113",
# "1112", "1111", "1110", "1109", "1108", "1107"]
The steps are as follows.
str = data.reduce('') { |s,h| s + h['user_ids'] + ',' }
=> "1120,1119,...1107,1120,1119,...1107,"
arr = str.scan(/\d+/)
#=> ["1120", "1119", "1118", "1117", "1116", "1115", "1114", "1113",
# "1112", "1111", "1110", "1109", "1108", "1107", "1120", "1119",
# "1118", "1117", "1116", "1115", "1114", "1113", "1112", "1111",
# "1110", "1109", "1108", "1107"]
arr.uniq
#=> ["1120", "1119", "1118", "1117", "1116", "1115", "1114", "1113",
# "1112", "1111", "1110", "1109", "1108", "1107"]
A problem with this approach is that the intermediate array arr
can be quite large if data
contains many elements (hashes) and for each element h
, h['user_ids'].split(',')
contains many elements. One way around that is to build a set, which of course contains unique elements, and then convert that set to an array at the end.
require 'set'
data.each_with_object(Set.new) { |h,set|
h["user_ids"].split(',').each { |s| set << s } }.to_a
#=> ["1120", "1119", "1118", "1117", "1116", "1115", "1114",
# "1113", "1112", "1111", "1110", "1109", "1108", "1107"]
See Set::new, Set#<< and Set#to_a.
Note that the array returned here contains the same elements as the array returned earlier, but in a different order. I assume that is no import.
Upvotes: 0
Reputation: 4709
If you use Rails, try this:
data.pluck('user_ids').join(',').split(',').uniq
If you don't use Rails:
data.map{ |d| d.dig('user_ids') }.join(',').split(',').uniq
Result:
#=> [
# "1120", "1119", "1118", "1117", "1116", "1115", "1114",
# "1113", "1112", "1111", "1110", "1109", "1108", "1107"
# ]
Upvotes: 2