agemoagemo / yahoo.com wrote:
> --- Robert Klemme <bob.news / gmx.net> wrote:
> > ?> %w{aa bb cc dd ee ff gg hh ii jj
> > kk}.each_window(3) {|*a| p a}
> > ["aa", "bb", "cc"]
> > ["bb", "cc", "dd"]
> > ["cc", "dd", "ee"]
> > ["dd", "ee", "ff"]
> > ["ee", "ff", "gg"]
> > ["ff", "gg", "hh"]
> > ["gg", "hh", "ii"]
> > ["hh", "ii", "jj"]
> > ["ii", "jj", "kk"]
> > => ["aa", "bb", "cc", "dd", "ee", "ff", "gg", "hh",
> > "ii", "jj", "kk"]
>
> Am I the only one who thinks this seems a little
> peculiar?
>
> If I were writing something using this sort of
> functionality, I think I'd need and expect
> output something like:
>
> [nil, "aa", "bb"]
> ["aa", "bb", "cc"]
> ["bb", "cc", "dd"]
> ["cc", "dd", "ee"]
> ["dd", "ee", "ff"]
> ["ee", "ff", "gg"]
> ["ff", "gg", "hh"]
> ["gg", "hh", "ii"]
> ["hh", "ii", "jj"]
> ["ii", "jj", "kk"]
> ["jj", "kk", nil]
>
> Admittedly, it'd be hard to that reasonably with a
> variable-size window of even length. But for a
> previous-current-next arrangement, it seems to make
> more sense to say "there is no previous" with a nil
> than to basically skip the first item.

module Enumerable
  def each_with_neighbors
    wind = [nil]
    each do |x|
      wind << x
      wind.shift if wind.size > 3
      yield *wind if wind.size == 3
    end
    wind << nil
    yield *wind[-3,3] if wind.size > 2
    self
  end
end

%w{aa bb cc dd ee ff gg hh ii jj kk}.each_with_neighbors {|*a| p a}
-->
[nil, "aa", "bb"]
["aa", "bb", "cc"]
["bb", "cc", "dd"]
["cc", "dd", "ee"]
["dd", "ee", "ff"]
["ee", "ff", "gg"]
["ff", "gg", "hh"]
["gg", "hh", "ii"]
["hh", "ii", "jj"]
["ii", "jj", "kk"]
["jj", "kk", nil]