はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
islice (Python)
def _get_by_slice(self, slc):
self.reset()
value = list(islice(self, slc.start, slc.stop, slc.step))
return value
分かりやすい記事。
どうする (Ruby)
def islice(iterable, *args)
start = args[0] || 0
stop = args[1] || Float::INFINITY
step = args[2] || 1
cnt = 0
if iterable.is_a?(String)
it = iterable.split('').to_enum
else
it = iterable.to_enum
end
start.times do
it.next
cnt += 1
end
loop do
yield it.next
cnt += 1
step.pred.times do
it.next
cnt += 1
end
if stop < cnt
break
end
end
end
enum
とyield
を利用して、islice
メソッドを作成するのが手っ取り早そう。
exma.rb
s = 0..10
ans = []
enum_for(:islice, s, 0, 3).each do |x|
ans << x
end
p ans
ans.clear
enum_for(:islice, s, 2, nil, 3).each do |x|
ans << x
end
p ans
ans.clear
enum_for(:islice, s, nil, nil).each do |x|
ans << x
end
p ans
s = (0..) # 無限大
ans.clear
enum_for(:islice, s, nil, nil).each do |x|
break if x > 8 # ようさそう
ans << x
end
p ans
s = 'abcdefghij'
ans.clear
enum_for(:islice, s, 0, 3).each do |x|
ans << x
end
p ans
s = 'a'..'j'
ans.clear
enum_for(:islice, s, 0, 3).each do |x|
ans << x
end
p ans
# output
[0, 1, 2, 3]
[2, 5, 8]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
["a", "b", "c", "d"]
["a", "b", "c", "d"]
途中で打ち切る遅延評価パターンが便利そう。
もしかしたら、Enumerable#lazy
辺りで実装可能かもしれませんが。
メモ
- Python の islice を学習した
- 百里を行く者は九十里を半ばとす