質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

4131閲覧

配列の中のハッシュのuniq処理

ryoya1122

総合スコア16

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

1グッド

1クリップ

投稿2020/03/22 19:00

RailsでTwitter風のSNSアプリを作っているのですが、

1.フォローしているアカウントのツイート
2.自分のツイート
3.フォローしているアカウントがリツイートしたツイート

をタイムラインに表示させるために一度それぞれでActiveRecodeRelationで取得したツイートをハッシュ化し、大元の1つの配列に入れているのですが、

1と3でツイートが重複する事があり、例えば自分がフォローしている二人がそれぞれのツイートをリツイートし合った場合に1にも3にも該当のツイートが格納される事になり、同じツイートが2回3回...と格納されてしまいます。

図で表すと

大元の配列[
-ハッシュ{
--id:1 , body:〇〇}
-ハッシュ{
--id:1 , body:〇〇 retweet:true(リツイートで流れたツイートか否かを判別するキー)}
-ハッシュ{
--id:2 , body:△△}
-ハッシュ{
--id:3 , body:□□}]

簡単に表すとこのような状況なのですが、これをそのままArray.uniqメソッドを使うと、
ハッシュの中の重複しているidの部分だけが削除されて、残りのbodyその他の部分は残ったままです。(ハッシュ自体が消されるわけではない)

理想の挙動としては、idが重複しているハッシュがある場合、retweetではない純粋なツイートのみを残すような書き方をしたいのですが、
いい方法が見つかりません。同じような経験をされている方いましたらご教授願いたいです。

現在のコード

ruby

1 @user = current_user 2 @users = @user.followings 3 @following_user_id = [] 4 @users.each do |following| 5 @following_user_id.push(following.id) 6 end 7 @following_user_id.push(current_user.id) 8 @retweet_ids = Retweet.where(user_id: @following_user_id) 9 @tweet_array = [] 10 @tweet_hash = Hash.new{[]} 11 @retweet_ids.each do |retweet_id| 12 @tweet_hash = Hash.new{[]} 13 @tweet_hash["id"]=retweet_id.tweet.id 14 @tweet_hash["body"]=retweet_id.tweet.body 15 @tweet_hash["user_id"]=retweet_id.tweet.user_id 16 @tweet_hash["status"]= 1 17 @tweet_hash["status_by"]= retweet_id.user_id 18 @tweet_hash["score"]= retweet_id.tweet.score 19 @tweet_hash["created_at"]= retweet_id.tweet.created_at 20 @tweet_hash["updated_at"]= retweet_id.tweet.updated_at 21 @tweet_array.push(@tweet_hash) 22 end 23 24 @follow_tweets = Tweet.where(user_id: @following_user_id) 25 26 @follow_tweets.each do |follow_tweet| 27 @tweet_hash = Hash.new{[]} 28 @tweet_hash["id"]=follow_tweet.id 29 @tweet_hash["body"]=follow_tweet.body 30 @tweet_hash["user_id"]=follow_tweet.user_id 31 @tweet_hash["status"]= 0 32 @tweet_hash["score"]= follow_tweet.score 33 @tweet_hash["created_at"]= follow_tweet.created_at 34 @tweet_hash["updated_at"]= follow_tweet.updated_at 35 @tweet_array.push(@tweet_hash) 36 end 37 @tweets = @tweet_array.sort_by! {|h| h["updated_at"]}.reverse
DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

retweetでないものが必ず含まれるのか、含まれない可能性があるのか、で変わります。
必ず含まれるなら
@tweet_array.reject{|tweet_hash| tweet_hash["body"].is_retweet?}

含まれない可能性があるなら
group_by_id = @tweet_array.group_by{|tweet_hash| tweet_hash["id"] }
としますと

{ id1 => [tweet_hash,tweet_hash,tweet_hash], id2 => [tweet_hash], id3 => [tweet_hash,tweet_hash] }

の様になりますから、
group_by_id.values.map{|tweet_hashs| この中から一つ選ぶ }
とします

tweet_hash["body"].is_retweet?この中から一つ選ぶ部分は見分け方を元に工夫してください

投稿2020/03/22 21:31

winterboum

総合スコア23347

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ryoya1122

2020/03/23 00:21

ありがとうございます。後者のコードで実装しました。 group_by_id.values.map{|a| a[0]} でとりあえずは実装しました。この中から一つ選ぶ方法は優先順位をもう少し細かく決めて後ほど細分化したいと思います。 これは質問とは直接関係ないのですが、この後配列をソートするつもりなのですが、 @tweets.sort_by! { |a| a[:created_at] } @tweets.sort! { |x, y| x[:created_at] <=> y[:created_at] } 色々この辺りを試しているのですが、どう書いてもデフォルトの順番から全くソートされず困っています。 自分で考えた原因は[:created_at]のキーからバリューを呼び出せていないかと考えたのですが、カラムやドキュメントなどを見ると、同じやり方で配列の中に組み込まれたハッシュをソートしている記事があったので、原因が突き止められず困っています。 tweet_hashの中には確実に"created_at"のキーはあります。 が、書いてる途中に気づいたのですが、ハッシュがシンボルではなく文字列のキーで設定されているので、呼び出せてないのかもしれません。 キーをシンボルにしてもう一度試してみます。とりあえずご回答ありがとうございました。とても助かりました。
ryoya1122

2020/03/23 00:26

シンボルに直したらうまくソートする事ができました。 文字列をキーにするよりやはりシンボルで管理する方がrubyとして綺麗ですし、メリットが多い事を自覚しました。 重ね重ねありがとうございます。
winterboum

2020/03/23 01:19

ところで @following_user_id ですが @following_user_id = @user.followings.map(&:id) でとれません?
ryoya1122

2020/03/23 01:29

確かにここeachで回すの凄い無駄な気がしてました。mapの理解がまだ不十分で、arrayをeachで回す処理をメソッド化したものだと思ってます。 複雑なメソッドが苦手で逃げているのですが、できる事の幅が広いメソッドなので、もっと勉強しようと思いました!! 該当の箇所はcurrent_userのidも込みで @following_user_id = @user.followings.map(&:id).push(current_user.id) のように修正させていただきました!多分コレで問題ない...?と思います。 なにからなにまでご指摘ありがたいです!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問