LoginSignup
3
0

More than 5 years have passed since last update.

RedisのSorted Setsで同一スコアの場合、順位をランダムにしたい

Last updated at Posted at 2018-03-08

タイトルの通り、Sorted Setsで取ってきたランキングで、同一のスコアの場合は順位をランダムにしたい。

# こんなデータがあったとして
ids_and_scores = [[10010818, 155.0],[10026928, 150.0],[10025650, 150.0],[10023988, 150.0],[10023708, 150.0],[10023820, 115.0],[10025925, 110.0],[10024209, 110.0]]

# ここと
[10026928, 150.0],[10025650, 150.0],[10023988, 150.0],[10023708, 150.0]

# ここの順番をランダムにしたい
[10025925, 110.0],[10024209, 110.0]

まずは重複しているスコアを取ってくる。

duplicate_scores = ids_and_scores.group_by { |id_score| id_score[1] }.select { |score, ary| 1 < ary.size }.keys
# => [150.0, 110.0]

重複しているスコアの場合は配列にまとめる。


last_score = 0
id_ary_tmp = ids_and_scores.inject([]) do |output, id_score|
  if duplicate_scores.include?(id_score[1])
    if output.last.class == Array && last_score == id_score[1]
      output.last << id_score[0]
    else
      output << [id_score[0]]
    end
  else
    output << id_score[0]
  end
  last_score = id_score[1]

  output
end
# => [10010818, [10026928, 10025650, 10023988, 10023708], 10023820, [10025925, 10024209]]

重複しているスコアの配列をシャッフルしてflattenで配列を作り直す。

id_ary = id_ary_tmp.map do |id_ids|
  if id_ids.class == Array
    id_ids.shuffle
  else
    id_ids
  end
end.flatten
# => [10010818, 10023988, 10025650, 10026928, 10023708, 10023820, 10024209, 10025925]

メソッドにまとめる。

# 同スコアの場合はランダムで順位づけしたい
def sort_id_considering_duplicate_scores(ids_and_scores)
  duplicate_scores = ids_and_scores.group_by { |id_score| id_score[1] }.select { |score, ary| 1 < ary.size }.keys
  last_score = 0
  id_ary_tmp = ids_and_scores.inject([]) do |output, id_score|
    if duplicate_scores.include?(id_score[1])
      if output.last.class == Array && last_score == id_score[1]
        output.last << id_score[0]
      else
        output << [id_score[0]]
      end
    else
      output << id_score[0]
    end
    last_score = id_score[1]
    output
  end

  id_ary = id_ary_tmp.map do |id_ids|
    if id_ids.class == Array
      id_ids.shuffle
    else
      id_ids
    end
  end
  id_ary.flatten
end

一応動いているっぽいけどもっとシンプルにできそう。。。

sort_id_considering_duplicate_scores(ids_and_scores)
# => [10010818, 10026928, 10023988, 10023708, 10025650, 10023820, 10024209, 10025925]

sort_id_considering_duplicate_scores(ids_and_scores)
# => [10010818, 10026928, 10023988, 10025650, 10023708, 10023820, 10024209, 10025925]

sort_id_considering_duplicate_scores(ids_and_scores)
# => [10010818, 10023708, 10025650, 10023988, 10026928, 10023820, 10024209, 10025925]

sort_id_considering_duplicate_scores(ids_and_scores)
# => [10010818, 10023988, 10025650, 10023708, 10026928, 10023820, 10024209, 10025925]

sort_id_considering_duplicate_scores(ids_and_scores)
# => [10010818, 10025650, 10023708, 10023988, 10026928, 10023820, 10025925, 10024209]

※バグがあったので一部修正。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0