LoginSignup
0
0

More than 1 year has passed since last update.

[py2rb] itertools.islice

Posted at

はじめに

移植やってます。
( 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

enumyieldを利用して、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 を学習した
  • 百里を行く者は九十里を半ばとす
0
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
0
0