配列の全ての要素が等しいか否か
mrkn
配列の全ての要素が等しいことはどう確認したら良いんだろう。
`ary.all? {|e| e == ary[0] }` これかな
usa
ary.uniq.size == 1
mrkn
なるほど > uniq
usa
all?でブロック引数より速そうな予感
いやでもaryがでかくてかつ全然要素が等しくなかったらそうでもないか。
mrkn
`ary.all? {|e| e.foo == ary[0].foo }` の場合はどうでしょう。map.uniq.size がいいかな
usa
all?は全て等しい時に遅いが、序盤で違うとわかったら速い
mrkn
確かに > 序盤で違うとわかったら速い
usa
この辺は予想される集合の傾向で判断するしかないですかねえ。
map.uniq.sizeはmapの結果としての一時配列を作らないようにするには、えーと
Enumerator
mrkn
一瞬 `ary.homogeneous? {|e| e.foo }` って書きたくなったけど、そのまま書いても読めるから大丈夫そうだ。
`ary.lazy.map(&:foo).uniq.size`
naruse
MJITがall?もはやくしてくれるさぁ
mrkn
all? がインライン展開されるのか。
sorah
lazy.uniqいけるのか。
.sizeじゃなくて .count?
usa
lazyだとsizeはまずい
mrkn
lazy 使う場合は count でした
sorah
`[1,1,1,1].lazy.uniq.take(2).count == 1` かなぁ
usa
だいぶテクニカルになってきたな
sorah
>> a = Struct.new(:i) { def n; p i; end }; [a.new(1), a.new(2), a.new(3), a.new(4)].lazy.map(&:n).uniq.take(2).count
1
2
=> 2
>> a = Struct.new(:i) { def n; p i; end }; [a.new(1), a.new(2), a.new(3), a.new(4)].lazy.map(&:n).uniq.count
1
2
3
4
=> 4
こういう差が。
usa
なるはや殺しっすよね
しかしさすがにここまでくると別名をつけたくなったね。
mrkn
take(2) 頭いいな
この take(2) は結構感動しました。
usa
さすがそらはパイセンですよね。
しかし `homogeneous?` ってわかりやすい名前なのかな。
tadd
https://ruby-gnome2.osdn.jp/ja/hiki.cgi?%A5%DC%A5%C3%A5%AF%A5%B9 ruby + homogeneous でぐぐったらGtkが引っかかった
mrkn
私が最初に思いついた名前なので、一般的ではないと思います。
ary.same_all? とかかな
usa
ぼくもsame_allかなあと思いました。
mrkn
activesupport にも存在しない
knu
`[1,1,1,1].each_cons(2).all? { |a,b| a == b }`
usa
なんとなく遅そうなイメージ
knu
なぜだろう
usa
比較が1回減るのはいいのだけど
(e0,e1) (e1,e2) (e2,e3) ... という舐め方が有利なのか不利なのかどっちだろう、という。
knu
ブロックが遅い気がする。簡略記法欲しいな
usa
ブロックはどうしても遅い
knu
`inject(:+)` はチート
計測すると、条件成立時や末尾に違う値がある場合は uniq が2倍以上速い
でも、ショートカットはしてくれないので最初の方に違う値が検出される場合は当然each_consが圧勝
usa
2倍以上かあ。
やはり想定されるデータセットにあわせて選ぶしかないですね。
knu
きっとone? があれば lazy.uniq.one? が最適解かな
(equality が eql? ってのはおいといて)
usa
あ、そういうのはまあそういうことで
knu
ショートカットがないは語弊があった。2つの値だけがずっと続く場合は〜、だ。
one? はたまーにほしいんだよな
何回か前のDeveloperMeetingで出てたか
と思ったらある?あれ?
usa
おっ
knu
一つだけが真の場合にtrueを返すのか
nilやfalseを考えないなら使えるか
`[1,1,1,1].lazy.uniq.one?` でよさそう
uniqだから 1 と 1.0 は区別される、one?だから nil や false が入る場合はダメ、という制約付き
sorah
ブロック無し `.any?`  を `.size > 0` 的に使ってるのと同じくらいの生理的嫌悪感がある
usa
わかる
sorah
あれ使ってる人は nil, false での動作理解して書いてんのかな、というのが分からなくて混乱するのでやめてほしいんだよな
knu
お、 `one?(&:object_id)` にしても速度落ちない
knu
Lispだと=がいくつでも引数取れるか `(apply #'= '(1 1 1 1)) `
ずるい
usa
ずるいよね
knu
Rubyのオブジェクト指向はレシーバと引数の間に偉さの違い
usa
Rubyしぐさ
knu
zipがたまに気持ち悪い
気持ちは a.zip(b,c) でなく [a,b,c].zip と書きたいんだ…
Array.zip(…) が配列を返して Enumerator.zip(…) はEnumerableを返す、というのは悪くないと思うんだけど字面がRubyっぽくないんだよな
mrkn
会社のブログで出題してみたら `ary.rotate == ary` というここでは出なかった解が出てきた。
usa
おー
遅そうw
でも柔軟な発想を感じる。すごい。
mrkn
似たようなので `ary[0..-2] == ary[1..-1]`
usa
rotateしないからこれはまだ。しかしかっこよさに欠けるな。
いや、これ実はむっちゃ速い?
mrkn
配列を作らない
usa
しかも評価もおそらく短絡してくれる。
mrkn
配列の長さが2以上の時の実装はコレでしょうな。
usa
1の時もいけるのでは
ko1
rotate
知らなかった
sorah
柔軟な発想だ…
usa
それを考えた人に今日の :100: をあげよう。
文句なし。
slackのログを上手いことまとめる方法が思いつかなかったので、雑にpreで……。