如何在Ruby中使用数组按类别组织待办事项列表?

wnvonmuf  于 2022-10-15  发布在  Ruby
关注(0)|答案(3)|浏览(93)

如何使用Ruby按类别打印数组元素?
这里我有todos一个数组数组:

todos = [
      ["Send invoice", "money"],
      ["Clean room", "organize"],
      ["Pay rent", "money"],
      ["Arrange books", "organize"],
      ["Pay taxes", "money"],
      ["Buy groceries", "food"]
    ]

我想为类别构建一个数组,如下所示:

[["money", ["Send invoice", "Pay rent", "Pay taxes"]], ...]

预期产量:

money:
     Send invoice
     Pay rent
     Pay taxes
   organize:
     Clean room
     Arrange books
   food:
     Buy groceries

这是我的尝试:

a, b, c = ["money"], ["organize"], ["food"]

for i in todos  
    if i[1]  ==  "money"
            arr = []
        a.push(arr.push(i[0]))  #=> ["money", ["Send invoice"], ["Pay rent"], ["Pay taxes"]]
    elsif i[1] == "organize"
            arr = []
        b.push(arr.push(i[0]))  #=> ["organize", ["Clean room"], ["Arrange books"]]
    else
            arr = []
        c.push(arr.push(i[0])). #=> ["food", ["Buy groceries"]]
    end 
end

**解释:**在我的代码中,我将值直接赋给了数组a, b, c = ["money"], ["organize"], ["food"],这是错误的。我怎样才能得到预期的产量?

mzmfm0qo

mzmfm0qo1#

我会这样做:

todos = [
  ["Send invoice", "money"],
  ["Clean room", "organize"],
  ["Pay rent", "money"],
  ["Arrange books", "organize"],
  ["Pay taxes", "money"],
  ["Buy groceries", "food"]
]

todos.group_by(&:last).map { |key, values| [key, values.map(&:first)] }

# => [["money", ["Send invoice", "Pay rent", "Pay taxes"]], ["organize", ["Clean room", "Arrange books"]], ["food", ["Buy groceries"]]]

这是怎么回事?Enumerable#group_by返回按其Array#last值分组的嵌套数组,并将返回如下所示的嵌套散列结构:

{
  "money"=>[["Send invoice", "money"], ["Pay rent", "money"], ["Pay taxes", "money"]],
  "organize"=>[["Clean room", "organize"], ["Arrange books", "organize"]],
  "food"=>[["Buy groceries", "food"]]
}

在方法链的下一步中,它使用Enumerable#map将每个键/值对转换为最终结构,方法是返回一个包含来自grouped_by的键的数组和一个仅包含来自原始值的first值的嵌套数组。例如,它将在一次迭代中接受此输入,并将其转换为:

{ "organize"=>[["Clean room", "organize"], ["Arrange books", "organize"]] }

# with `key` being "organize", and `values` being the nested arrays on the right

# getting translated into:

# => ["organize", ["Clean room", "Arrange books"]]
vybvopom

vybvopom2#

我们可以使用#each_with_objecttodos上迭代,构建一个散列,对于这个任务来说,这似乎是一个更有用的数据结构。

h = todos.each_with_object({}) do |arr, h|
  task, category = arr 
  h[category] ||= []
  h[category] << task 
end

# => {"money"=>["Send invoice", "Pay rent", "Pay taxes"],

# "organize"=>["Clean room", "Arrange books"],

# "food"=>["Buy groceries"]}

这样做相当于:

h = {}

for arr in todos
  task = arr.first
  category = arr.last

  h[category] = [] unless h.has_key? category
  h[category].push(task)
end

要把它变成数组的数组。

h.map { |k, v| [k, v] }

# => [["money", ["Send invoice", "Pay rent", "Pay taxes"]],

# ["organize", ["Clean room", "Arrange books"]],

# ["food", ["Buy groceries"]]]
wooyq4lh

wooyq4lh3#

todos = [
  ["Send invoice", "money"],
  ["Clean room", "organize"],
  ["Pay rent", "money"],
  ["Arrange books", "organize"],
  ["Pay taxes", "money"],
  ["Buy groceries", "food"]
]

todos.group_by(&:last).transform_values{ |v| v.map(:first) }

在这里,我们使用带有速记方法调用的group_by方法,这将返回一个散列,其中键是块的计算结果,值是集合中与键对应的元素数组。
我们还对块使用transform_values方法,并根据给定的块对哈希值进行转换
上述陈述的结果

=> {"money"=>["Send invoice", "Pay rent", "Pay taxes"], "organize"=>["Clean room", "Arrange books"], "food"=>["Buy groceries"]}

相关问题