I have an array of hashes like
@data_records = [
{"user": "user1", "key1": "v1k1", ... , "keyN": "v1kN"},
{"user": "user2", "key1": "v2k1", ... , "keyN": "v2kN"},
{"user": "user3", "key1": "v3k1", ... , "keyN": "v3kN"},
{"user": "user1", "key1": "v4k1", ... , "keyN": "v4kN"},
{"user": "user1", "key1": "v5k1", ... , "keyN": "v5kN"},
{"user": "user4", "key1": "v6k1", ... , "keyN": "v6kN"},
]
As you may see, I may have many 'records' for the same user. In the example above, user1 has three records, for instance.
Now I need, based on this array of hashes, to generate an array with a single entry for every user in it. I mean, I need
[ "user1", "user2", "user3", "user4" ]
but not
[ "user1", "user2", "user3", "user1", "user1", "user4" ].
I wrote the following piece of code, which does the job:
def users_array
arr = Array.new
@data_records.each { |item| arr.push(item["user"]) if not arr.include?(item["user"])}
arr
end
But it bothers me the fact I must use the auxiliary variable arr for this to work. I'm sure there is a shorter way to to this with Array#map method. Since Array#map returns an array, it could be something like
def users_array
@data_records.map { |item| item["user"] if ... }
end
The problem is I don't know how to mention the array I'm creating with Array#map inside the block. I believe it could be something like
def users_array
@data_records.map { |item| item["user"] if not this.include?(item["user"]) }
end
but it doesn't work, of course.
Can someone tell if there is a way to do this?
EDIT
Yes, I could use Array#uniq to do this. But then I rephrase the question: Is there a way to refer to the implicit array created by map inside the map's block?
@data_records.map { |item| item["user"] }.uniq?map, no; but you could do so withreduceorinject:@data_records.inject([]) { |memo, item| memo << item["user"] unless memo.include? item["user"]; memo }