Making a count of unique elements in an array

D

Dan Kohn

Given an array, I need to produce a two-dimensional resulting array
where each pair consists of a unique element from the original array
and the number of times that element appears.

I found two ways to do this. Is one of them better? Is there a better
way?

arr = %w{a b b c c d e e e}
p arr
p arr.uniq.map {|e| [e, (arr.select {|ee| ee == e}).size ]}
counter = {}
arr.each {|e| counter[e] += 1 rescue counter[e] = 1 }
p counter.to_a


outputs:

["a", "b", "b", "c", "c", "d", "e", "e", "e"]
[["a", 1], ["b", 2], ["c", 2], ["d", 1], ["e", 3]]
[["a", 1], ["b", 2], ["c", 2], ["d", 1], ["e", 3]]
 
R

Robert Klemme

Dan said:
Given an array, I need to produce a two-dimensional resulting array
where each pair consists of a unique element from the original array
and the number of times that element appears.

I found two ways to do this. Is one of them better? Is there a
better way?

arr = %w{a b b c c d e e e}
p arr
p arr.uniq.map {|e| [e, (arr.select {|ee| ee == e}).size ]}
counter = {}
arr.each {|e| counter[e] += 1 rescue counter[e] = 1 }
p counter.to_a


outputs:

["a", "b", "b", "c", "c", "d", "e", "e", "e"]
[["a", 1], ["b", 2], ["c", 2], ["d", 1], ["e", 3]]
[["a", 1], ["b", 2], ["c", 2], ["d", 1], ["e", 3]]

I like #inject 1-liners:
arr = %w{a b b c c d e e e} => ["a", "b", "b", "c", "c", "d", "e", "e", "e"]
arr.inject(Hash.new(0)) {|h,x| h[x]+=1;h} => {"a"=>1, "b"=>2, "c"=>2, "d"=>1, "e"=>3}
arr.inject(Hash.new(0)) {|h,x| h[x]+=1;h}.to_a => [["a", 1], ["b", 2], ["c", 2], ["d", 1], ["e", 3]]
arr.inject(Hash.new(0)) {|h,x| h[x]+=1;h}.sort
=> [["a", 1], ["b", 2], ["c", 2], ["d", 1], ["e", 3]]

:)

Kind regards

robert
 
N

Norbert Melzer

if i have to count no. of distinct elements in a 2D array ,then what
to do??

I think at least one of this will do it:

```
[1] pry(main)> [[1,2],[2,3],[1,2]].count
=> 3
[2] pry(main)> [[1,2],[2,3],[1,2]].uniq
=> [[1, 2], [2, 3]]
[3] pry(main)> [[1,2],[2,3],[1,2]].uniq.count
=> 2
[4] pry(main)> [[1,2],[2,3],[1,2]].flatten
=> [1, 2, 2, 3, 1, 2]
[5] pry(main)> [[1,2],[2,3],[1,2]].flatten.uniq
=> [1, 2, 3]
[6] pry(main)> [[1,2],[2,3],[1,2]].flatten.uniq.count
=> 3
```

There is a very beautiful ressource:
<http://www.ruby-doc.org/core-2.0.0/Array.html>

You can find nearly anything about arrays there…

HTH
Norbert
 
R

Robert Klemme

if i have to count no. of distinct elements in a 2D array ,then what to do??

Iterate and count. For counting you can use a Hash with default value 0.

Cheers

robert
 
L

lukeabergen

Another way is the super-useful group_by and map

arr = ["a", "b", "b", "c", "c", "d", "e", "e", "e"]
grouped = arr.group_by {|x| x} #=> produces something like {"a" => ["a"], "b" => ["b", "b"], etc...
result = grouped.map {|el, arr| [el, arr.count]}
 
R

Robert Klemme

Another way is the super-useful group_by and map

arr = ["a", "b", "b", "c", "c", "d", "e", "e", "e"]
grouped = arr.group_by {|x| x} #=> produces something like {"a" => ["a"], "b" => ["b", "b"], etc...
result = grouped.map {|el, arr| [el, arr.count]}

Downside of that approach is that it does unnecessary work and uses more
memory than necessary. And the result is not a Hash which may make
retrieval of the counts of an element quite expensive if there are many
different values.

Btw, the OP spoke of a "2D array". So the input likely looks different
than in your example. We also do not know what he actually wants to
count. Is it individual elements? Or does "distinct elements" refer to
a single array?

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,818
Messages
2,569,732
Members
45,691
Latest member
Dick331194

Latest Threads

Top