Ruby 按嵌套数组分组数组

Ruby 按嵌套数组分组数组,ruby,grouping,Ruby,Grouping,我有一个以下格式的数组: [ { day: 1 intervals: [ { from: 900, to: 1200 } ] }, { day: 2 intervals: [ { from: 900, to: 1200 } ] }, { day: 3 intervals: [ { from: 90

我有一个以下格式的数组:

[ 
  { day: 1
    intervals: [
      {
        from: 900,
        to: 1200
      }
    ]
  },
  { day: 2
    intervals: [
      {
        from: 900,
        to: 1200
      }
    ]
  },
  { day: 3
    intervals: [
      {
        from: 900,
        to: 1200
      }
    ]
  },
  { day: 4
    intervals: [
      {
        from: 900,
        to: 1200
      }
    ]
  },
  { day: 5
    intervals: [
      {
        from: 900,
        to: 1200
      }
    ]
  },
  { day: 6
    intervals: [
      {
        from: 900,
        to: 1200
      },
      {
        from: 1300,
        to: 2200
      }
    ]
  },
  { day: 7
    intervals: [
      {
        from: 900,
        to: 1200
      },
      {
        from: 1300,
        to: 2200
      }
    ]
  }
]
我不想这样把他们分组:

[ 
  { day: 1-5
    intervals: [
      {
        from: 900,
        to: 1200
      }
    ]
  },
  { day: 6-7
    intervals: [
      {
        from: 900,
        to: 1200
      },
      {
        from: 1300,
        to: 2200
      }
    ]
  }
]
标准:
  • 仅当间隔相同时才分组
  • 仅当匹配项按时间顺序排列(即1-5或1-3,而不是1-2-5)时才分组

如何实现这一点?

您需要研究阵列。您需要重新映射数组,并使用上面的“分组”逻辑对其进行迭代以提取所需的数据。

您需要查找数组。您需要重新映射数组并对其进行迭代,以使用上面的“分组”逻辑提取所需的数据。

这将生成所需的输出:

by_interval = data.inject({}) do | a, e |
  i = e[:intervals]
  a[i] ||= []
  a[i] << e[:day].to_i
  a
end

result = by_interval.map do | interval, days |
  slices = days.sort.inject([]) do | a, e |
    a << [] if a == [] || a.last.last != e - 1
    a.last << e
    a
  end
  slices.map do | slice |
      {:day => "#{slice.first}-#{slice.last}", :intervals => interval }
  end
end
result.flatten!
by_interval=data.injection({})do|a,e|
i=e[:间隔]
a[i]| |=[]

a[i]这将产生所需的输出:

by_interval = data.inject({}) do | a, e |
  i = e[:intervals]
  a[i] ||= []
  a[i] << e[:day].to_i
  a
end

result = by_interval.map do | interval, days |
  slices = days.sort.inject([]) do | a, e |
    a << [] if a == [] || a.last.last != e - 1
    a.last << e
    a
  end
  slices.map do | slice |
      {:day => "#{slice.first}-#{slice.last}", :intervals => interval }
  end
end
result.flatten!
by_interval=data.injection({})do|a,e|
i=e[:间隔]
a[i]| |=[]

a[i]这里是@joelparkerhenderson解决方案的一个变体,它试图更接近您的需求,重新格式化输出等

output = []

grouped = input.group_by do |x|
  x[:intervals]
end

grouped.each_pair do |k, v|
  days = v.map {|day| day[:day]}
  if days.each_cons(2).all? { |d1, d2| d1.next == d2 }
    output << {
      :days => days.values_at(0,-1).join('-'),
      :intervals => k
    }
  end
end

puts output
output=[]
分组=输入。按do | x分组|
x[:间隔]
结束
分组。每对do | k,v|
days=v.map{| day | day[:day]}
如果是天,每个都是(2)。全部?{| d1,d2 | d1.next==d2}
输出天数。值_位于(0,-1)。联接('-'),
:间隔=>k
}
结束
结束
输出

这里是@joelparkerhenderson解决方案的一个变体,它试图更接近您的需求,重新格式化输出等

output = []

grouped = input.group_by do |x|
  x[:intervals]
end

grouped.each_pair do |k, v|
  days = v.map {|day| day[:day]}
  if days.each_cons(2).all? { |d1, d2| d1.next == d2 }
    output << {
      :days => days.values_at(0,-1).join('-'),
      :intervals => k
    }
  end
end

puts output
output=[]
分组=输入。按do | x分组|
x[:间隔]
结束
分组。每对do | k,v|
days=v.map{| day | day[:day]}
如果是天,每个都是(2)。全部?{| d1,d2 | d1.next==d2}
输出天数。值_位于(0,-1)。联接('-'),
:间隔=>k
}
结束
结束
输出

扩展@Michael Kohl的答案

output = []

grouped = schedules.as_json.group_by do |x|
  x['intervals']
end

grouped.each_pair do |k, v|
  days = v.map {|day| day['day']}
  grouped_days = days.inject([[]]) do |grouped, num|
    if grouped.last.count == 0 or grouped.last.last == num - 1
      grouped.last << num
    else
      grouped << [ num ]
    end
    grouped
  end

  grouped_days.each do |d|
    output << {
      heading: d.values_at(0, -1).uniq.join('-'),
      interval: k
    }
  end
end

output
output=[]
分组=schedules.as_json.group_by do|x|
x[“间隔”]
结束
分组。每对do | k,v|
days=v.map{| day | day['day']}
分组天=天。注入([[])do |分组,num|
如果grouped.last.count==0或grouped.last.last==num-1

最后扩展@Michael Kohl的答案

output = []

grouped = schedules.as_json.group_by do |x|
  x['intervals']
end

grouped.each_pair do |k, v|
  days = v.map {|day| day['day']}
  grouped_days = days.inject([[]]) do |grouped, num|
    if grouped.last.count == 0 or grouped.last.last == num - 1
      grouped.last << num
    else
      grouped << [ num ]
    end
    grouped
  end

  grouped_days.each do |d|
    output << {
      heading: d.values_at(0, -1).uniq.join('-'),
      interval: k
    }
  end
end

output
output=[]
分组=schedules.as_json.group_by do|x|
x[“间隔”]
结束
分组。每对do | k,v|
days=v.map{| day | day['day']}
分组天=天。注入([[])do |分组,num|
如果grouped.last.count==0或grouped.last.last==num-1

grouped.last Hi,感谢您的回答,我确实知道map/collect,但在比较每天的哈希值时遇到困难。嗨,感谢您的回答,我确实知道map/collect,但在比较每天的哈希值时遇到困难。请注意,您的示例输出没有满足第二个要求<代码>6-7
只有2天。哦,你说得对!删除了该标准。谢谢请注意,示例输出不满足第二个要求<代码>6-7
只有2天。哦,你说得对!删除了该标准。谢谢如果第1天、第2天、第3天、第5天的时间间隔相同,您的代码将不属于第1-3组,对吗?没错,这当然可以改进。我发现这是解决我的问题的最佳起点,非常感谢!如果第1天、第2天、第3天、第5天的时间间隔相同,您的代码将不属于第1-3组,对吗?没错,这当然可以改进。我发现这是解决我的问题的最佳起点,非常感谢!