在 Ruby 中循环主集、处理每个子集的最简洁方法

发布于 2024-10-17 08:15:21 字数 1428 浏览 9 评论 0原文

这是一种常见的情况,我对解决方案一直不太满意。您有一组数据,在本例中假设数据库中的行按类别排序。

您想要构建一个包含每个类别的子集的缓冲区,并对每个类别的更改进行一些处理,然后清除缓冲区。假设 process() 包含在一堆您不想重复的复杂逻辑中

有人有更好的设置吗?

# category, city
data = [
          [10, 'citya'],
          [10, 'cityb'],
          [11, 'citya'],
          [11, 'cityb'],
          [11, 'citya'],
          [12, 'cityb'],
          [12, 'cityg']
       ]

# do some heavy lifting in here
def process(buf) p buf; end

cur_cat = nil
cur_cat_buf = []
data.each do |r|
  if r[0] != cur_cat
    cur_cat = r[0]
    process(cur_cat_buf) #<-- assume this is conditional, complex
    cur_cat_buf.clear
  end
  cur_cat_buf << r[1]
end
process(cur_cat_buf) #<-- assume the conditional is duplicated...ack.

这是另一种技术,而且非常糟糕。乱七八糟,糟透了!总是向前看,检查它是否为零或不同等等...呃...

cur_cat = data[0][0] if data.length > 0
cur_cat_buf = []
data.each_with_index do |r, i|
  cur_cat_buf << r[1]

  # look ahead
  if data[i+1] == nil or data[i+1][0] != cur_cat
    cur_cat = data[i+1][0] if data[i+1] != nil
    process(cur_cat_buf)
    cur_cat_buf.clear
  end
end

这是另一种选择。当然比上一张好。

cur_cat = nil
cur_cat_buf = []
for i in 0..(data.length)
  if (r = data[i]) == nil or r[0] != cur_cat
    process(cur_cat_buf)
    break unless r

    cur_cat_buf.clear
    cur_cat = r[0]
  end

  cur_cat_buf << r[1]
end

我想要一个干净、优雅的解决方案。一定有更好的办法!

This is a common scenario and I'm never quite happy with the solutions. You have a set of data, just assume rows from a db ordered by category in this case.

You want to build a buffer with a sub-set of each category, and on each category change, do some processing, then clear the buffer. Assume that process() is wrapped in a bunch of complex logic that you don't want to duplicate

Anyone have a better setup?

# category, city
data = [
          [10, 'citya'],
          [10, 'cityb'],
          [11, 'citya'],
          [11, 'cityb'],
          [11, 'citya'],
          [12, 'cityb'],
          [12, 'cityg']
       ]

# do some heavy lifting in here
def process(buf) p buf; end

cur_cat = nil
cur_cat_buf = []
data.each do |r|
  if r[0] != cur_cat
    cur_cat = r[0]
    process(cur_cat_buf) #<-- assume this is conditional, complex
    cur_cat_buf.clear
  end
  cur_cat_buf << r[1]
end
process(cur_cat_buf) #<-- assume the conditional is duplicated...ack.

This is the other technique, and is just terrible. Messy, awful! Always looking ahead, checking if it is nil or different etc...ugh...

cur_cat = data[0][0] if data.length > 0
cur_cat_buf = []
data.each_with_index do |r, i|
  cur_cat_buf << r[1]

  # look ahead
  if data[i+1] == nil or data[i+1][0] != cur_cat
    cur_cat = data[i+1][0] if data[i+1] != nil
    process(cur_cat_buf)
    cur_cat_buf.clear
  end
end

This is another alternative. Certainly better than the last one.

cur_cat = nil
cur_cat_buf = []
for i in 0..(data.length)
  if (r = data[i]) == nil or r[0] != cur_cat
    process(cur_cat_buf)
    break unless r

    cur_cat_buf.clear
    cur_cat = r[0]
  end

  cur_cat_buf << r[1]
end

I want a clean, elegant solution. There's gotta be a better way!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不可一世的女人 2024-10-24 08:15:21
data.group_by(&:first).each_value {|buffer| process(buffer.map &:last) }
data.group_by(&:first).each_value {|buffer| process(buffer.map &:last) }
爱她像谁 2024-10-24 08:15:21
data.group_by(&:first).each_value do |pairs| 
  process(pairs.map(&:last)) 
end

或者等效的,但稍微更详细,但更明确:

data.group_by { |category_id, city| category_id }.each_value do |pairs| 
  process(pairs.map { |category_id, cities| cities }) 
end
data.group_by(&:first).each_value do |pairs| 
  process(pairs.map(&:last)) 
end

Or the equivalent, yet slightly more verbose, yet slightly more explicit:

data.group_by { |category_id, city| category_id }.each_value do |pairs| 
  process(pairs.map { |category_id, cities| cities }) 
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文