eastafri
eastafri

Reputation: 2226

How to return the index of the array items occuring under a certain threshold

In Ruby, given an array of elements, what is the easiest way to return the indices of the elements that are not identical?

array = ['a','b','a','a','a','c'] #=> [1,5]

Expanded question:

Assuming that the identity threshold is based on the most frequent element in the array.

array =  ['a','c','a','a','a','d','d'] #=> [1,5,6]

For an array with two equally frequent elements, return the indices of either of the 2 elements. e.g.

array = ['a','a','a','b','b','b'] #=>[0,1,2] or #=> [3,4,5]

Upvotes: 1

Views: 241

Answers (2)

Emiliano Poggi
Emiliano Poggi

Reputation: 24816

Answer edited after question edit:

def idx_by_th(arr)
    idx = [] 
    occur = arr.inject(Hash.new(0)) { |k,v| k[v] += 1; k }
    th = arr.sort_by { |v| occur[v] }.last
    arr.each_index {|i| idx << i if arr[i]!=th}
    idx
end

idx_by_th ['a','b','a','a','a','c']  # => [1, 5]
idx_by_th ['a','c','a','a','a','d','d'] # => [1, 5, 6]
idx_by_th ['a','a','a','b','b','b'] # => [0, 1, 2]

These answers are valid for the first version of the question:

ruby < 1.8.7

def get_uniq_idx(arr)
    test=[]; idx=[]
    arr.each_index do |i|
        idx << i if !(arr[i+1..arr.length-1] + test).include?(arr[i])
        test << arr[i]
    end
    return idx
end

puts get_uniq_idx(['a','b','a','a','a','c']).inspect # => [1, 5]

ruby >= 1.8.7:

idxs=[]
array.each_index {|i| idxs<<i if !(array.count(array[i]) > 1)}
puts idxs.inspect # => [1, 5]

Upvotes: 1

Chowlett
Chowlett

Reputation: 46667

It's not quite clear what you're looking for, but is something like this what you want?

array = ['a','b','a','a','a','c']
array.uniq.inject([]) do |arr, elem| 
  if array.count(elem) == 1
    arr << array.index(elem)
  end
  arr
end

# => [1,5]

Upvotes: 1

Related Questions