Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 基于比较相邻元素的Ruby/Rails组数组_Ruby On Rails_Ruby_Arrays - Fatal编程技术网

Ruby on rails 基于比较相邻元素的Ruby/Rails组数组

Ruby on rails 基于比较相邻元素的Ruby/Rails组数组,ruby-on-rails,ruby,arrays,Ruby On Rails,Ruby,Arrays,我有一个有序的数组,里面有很多对象,我想通过将它们与周围的元素进行比较来对它们进行分组 a按start属性排序 a = [{ name: "joe", start: "9am", end: "10am" }, { name: "joe", start: "10am", end: "11am" }, { name: "harry", start: "11am", end: "12pm" }, { name: "harry", start: "12pm

我有一个有序的数组,里面有很多对象,我想通过将它们与周围的元素进行比较来对它们进行分组

a
start
属性排序

 a = [{ name: "joe",   start: "9am",  end: "10am" },
      { name: "joe",   start: "10am", end: "11am" },
      { name: "harry", start: "11am", end: "12pm" },
      { name: "harry", start: "12pm", end: "1pm"  },
      { name: "harry", start: "2pm",  end: "3pm"  },
      { name: "joe",   start: "3pm",  end: "4pm"  },
      { name: "joe",   start: "4pm",  end: "5pm"  }]
我想按
name
属性对相邻对象进行分组,但前提是
start
end
时间相同,从而产生:

    a = [[{ name: "joe",   start: "9am",  end: "10am" }, { name: "joe",   start: "10am", end: "11am" }],
         [{ name: "harry", start: "11am", end: "12pm" }, { name: "harry", start: "12pm", end: "1pm"  }],
         [{ name: "harry", start: "2pm",  end: "3pm"  }],
         [{ name: "joe",   start: "3pm",  end: "4pm"  }, { name: "joe",   start: "4pm",  end: "5pm"  }]]
连续时间段的数量没有最大值


我可以按
名称对它们进行分组,如果相邻,如图所示:

但是,我似乎无法使用chunk获取元素索引来进行
开始
结束
时间比较


答案似乎是这样的:

但是我在写我自己的函数时失败得很惨。(我很难理解
slice\u在
之前做了什么。)

任何帮助都将不胜感激

这里有一种使用and的方法。不过,它需要Ruby 2.2+

require 'time' # for sorting times

a = [{ name: "joe",   start: "9am",  end: "10am" },
     { name: "joe",   start: "10am", end: "11am" },
     { name: "harry", start: "11am", end: "12pm" },
     { name: "harry", start: "12pm", end: "1pm"  },
     { name: "harry", start: "2pm",  end: "3pm"  },
     { name: "joe",   start: "3pm",  end: "4pm"  },
     { name: "joe",   start: "4pm",  end: "5pm"  }]

a.sort_by { |h| [ h[:name], Time.parse(h[:start]) ] }                     # 1
 .slice_when { |x, y| x[:end] != y[:start] || x[:name] != y[:name] }.to_a # 2
产生

=> [[{:name=>"harry", :start=>"11am", :end=>"12pm"}, {:name=>"harry", :start=>"12pm", :end=>"1pm"}],
    [{:name=>"harry", :start=>"2pm", :end=>"3pm"}],
    [{:name=>"joe", :start=>"9am", :end=>"10am"}, {:name=>"joe", :start=>"10am", :end=>"11am"}],
    [{:name=>"joe", :start=>"3pm", :end=>"4pm"}, {:name=>"joe", :start=>"4pm", :end=>"5pm"}]]
以下是一个带有中间结果的逐步解释:

1) 在名称中按名称和时间对哈希进行排序。请注意使用
Time.parse
将时间字符串临时转换为
Time
对象以进行适当排序:

 => [{:name=>"harry", :start=>"11am", :end=>"12pm"},
     {:name=>"harry", :start=>"12pm", :end=>"1pm"},
     {:name=>"harry", :start=>"2pm", :end=>"3pm"},
     {:name=>"joe", :start=>"9am", :end=>"10am"},
     {:name=>"joe", :start=>"10am", :end=>"11am"},
     {:name=>"joe", :start=>"3pm", :end=>"4pm"},
     {:name=>"joe", :start=>"4pm", :end=>"5pm"}]
2) 现在,使用Daniel Polfer的解决方案,当前者的结束时间不等于后者的开始时间或名称不匹配时,切片这个中间数组。这将返回一个
枚举器
对象,因此最后的
方法调用:

=> [[{:name=>"harry", :start=>"11am", :end=>"12pm"}, {:name=>"harry", :start=>"12pm", :end=>"1pm"}],
    [{:name=>"harry", :start=>"2pm", :end=>"3pm"}],
    [{:name=>"joe", :start=>"9am", :end=>"10am"}, {:name=>"joe", :start=>"10am", :end=>"11am"}],
    [{:name=>"joe", :start=>"3pm", :end=>"4pm"}, {:name=>"joe", :start=>"4pm", :end=>"5pm"}]]
如果您的散列已经预排序,那么Daniel Polfer的解决方案应该可以正常工作。但是,如果您有任何数据的名称和/或开始时间不符合以下顺序:

b = [{:name=>"joe", :start=>"3pm", :end=>"4pm"},
     {:name=>"bill", :start=>"2pm", :end=>"3pm"},
     {:name=>"joe", :start=>"5pm", :end=>"6pm"},
     {:name=>"joe", :start=>"4pm", :end=>"5pm"}] 
返回时,只需使用
slice\u

=> [[{:name=>"joe", :start=>"3pm", :end=>"4pm"}],
    [{:name=>"bill", :start=>"2pm", :end=>"3pm"}],
    [{:name=>"joe", :start=>"5pm", :end=>"6pm"}],
    [{:name=>"joe", :start=>"4pm", :end=>"5pm"}]]
而不是

=> [[{:name=>"bill", :start=>"2pm", :end=>"3pm"}],
    [{:name=>"joe", :start=>"3pm", :end=>"4pm"},
     {:name=>"joe", :start=>"4pm", :end=>"5pm"},
     {:name=>"joe", :start=>"5pm", :end=>"6pm"}]]
这里有一种使用和的方法。不过,它需要Ruby 2.2+

require 'time' # for sorting times

a = [{ name: "joe",   start: "9am",  end: "10am" },
     { name: "joe",   start: "10am", end: "11am" },
     { name: "harry", start: "11am", end: "12pm" },
     { name: "harry", start: "12pm", end: "1pm"  },
     { name: "harry", start: "2pm",  end: "3pm"  },
     { name: "joe",   start: "3pm",  end: "4pm"  },
     { name: "joe",   start: "4pm",  end: "5pm"  }]

a.sort_by { |h| [ h[:name], Time.parse(h[:start]) ] }                     # 1
 .slice_when { |x, y| x[:end] != y[:start] || x[:name] != y[:name] }.to_a # 2
产生

=> [[{:name=>"harry", :start=>"11am", :end=>"12pm"}, {:name=>"harry", :start=>"12pm", :end=>"1pm"}],
    [{:name=>"harry", :start=>"2pm", :end=>"3pm"}],
    [{:name=>"joe", :start=>"9am", :end=>"10am"}, {:name=>"joe", :start=>"10am", :end=>"11am"}],
    [{:name=>"joe", :start=>"3pm", :end=>"4pm"}, {:name=>"joe", :start=>"4pm", :end=>"5pm"}]]
以下是一个带有中间结果的逐步解释:

1) 在名称中按名称和时间对哈希进行排序。请注意使用
Time.parse
将时间字符串临时转换为
Time
对象以进行适当排序:

 => [{:name=>"harry", :start=>"11am", :end=>"12pm"},
     {:name=>"harry", :start=>"12pm", :end=>"1pm"},
     {:name=>"harry", :start=>"2pm", :end=>"3pm"},
     {:name=>"joe", :start=>"9am", :end=>"10am"},
     {:name=>"joe", :start=>"10am", :end=>"11am"},
     {:name=>"joe", :start=>"3pm", :end=>"4pm"},
     {:name=>"joe", :start=>"4pm", :end=>"5pm"}]
2) 现在,使用Daniel Polfer的解决方案,当前者的结束时间不等于后者的开始时间或名称不匹配时,切片这个中间数组。这将返回一个
枚举器
对象,因此最后的
方法调用:

=> [[{:name=>"harry", :start=>"11am", :end=>"12pm"}, {:name=>"harry", :start=>"12pm", :end=>"1pm"}],
    [{:name=>"harry", :start=>"2pm", :end=>"3pm"}],
    [{:name=>"joe", :start=>"9am", :end=>"10am"}, {:name=>"joe", :start=>"10am", :end=>"11am"}],
    [{:name=>"joe", :start=>"3pm", :end=>"4pm"}, {:name=>"joe", :start=>"4pm", :end=>"5pm"}]]
如果您的散列已经预排序,那么Daniel Polfer的解决方案应该可以正常工作。但是,如果您有任何数据的名称和/或开始时间不符合以下顺序:

b = [{:name=>"joe", :start=>"3pm", :end=>"4pm"},
     {:name=>"bill", :start=>"2pm", :end=>"3pm"},
     {:name=>"joe", :start=>"5pm", :end=>"6pm"},
     {:name=>"joe", :start=>"4pm", :end=>"5pm"}] 
返回时,只需使用
slice\u

=> [[{:name=>"joe", :start=>"3pm", :end=>"4pm"}],
    [{:name=>"bill", :start=>"2pm", :end=>"3pm"}],
    [{:name=>"joe", :start=>"5pm", :end=>"6pm"}],
    [{:name=>"joe", :start=>"4pm", :end=>"5pm"}]]
而不是

=> [[{:name=>"bill", :start=>"2pm", :end=>"3pm"}],
    [{:name=>"joe", :start=>"3pm", :end=>"4pm"},
     {:name=>"joe", :start=>"4pm", :end=>"5pm"},
     {:name=>"joe", :start=>"5pm", :end=>"6pm"}]]

详细,但按您呈现的顺序给出结果,并使用较旧版本的Ruby

a.inject([]) do |result,hash| 
  if (!result.empty? && 
      (result.last.last[:name] == hash[:name]) && 
      (result.last.last[:end] == hash[:start]))
    result.last << hash
  else
    result << [hash]
  end
  result
end
a.inject([])do | result,hash |
如果(!result.empty?&&
(result.last.last[:name]==散列[:name])&&
(result.last.last[:end]==散列[:start]))

result.lastVerbose,但按您呈现的顺序给出结果,并与旧版本的Ruby一起使用

a.inject([]) do |result,hash| 
  if (!result.empty? && 
      (result.last.last[:name] == hash[:name]) && 
      (result.last.last[:end] == hash[:start]))
    result.last << hash
  else
    result << [hash]
  end
  result
end
a.inject([])do | result,hash |
如果(!result.empty?&&
(result.last.last[:name]==散列[:name])&&
(result.last.last[:end]==散列[:start]))
结果:最后一次使用切片前:

y=a[0]
a.slice_before { |hash| x=y 
                        y = hash
                        x[:name] != y[:name] || x[:end] != y[:start]
                        }.to_a
使用slice_之前:

y=a[0]
a.slice_before { |hash| x=y 
                        y = hash
                        x[:name] != y[:name] || x[:end] != y[:start]
                        }.to_a


那么你想为同一个人分组相邻时间?最多两次吗?或者可能有很多?没有最大值,可能有很多。你的意思是在一个组中有很多?是的,很多连续的时间段。你想为同一个人分组相邻的时间吗?最大值是两个吗?或者可能有很多?没有最大值,可能有很多。你是说一组中有很多?是的,很多连续的时间周期!真是一种享受!不过ruby 2.2版本更干净一些。a.slice_当{h1,h2 |(h1[:name]!=h2[:name])|(h1[:end]!=h2[:start])时。to_a利用了2.2的另一个答案,但为了相同的结果将其减少了一点。只是在适当的地方切片。哦,这是一个非常简单的方法@丹尼尔波尔弗:很好!你应该把它加到你的答案里。那比我的简单多了!美好的真是一种享受!不过ruby 2.2版本更干净一些。a.slice_当{h1,h2 |(h1[:name]!=h2[:name])|(h1[:end]!=h2[:start])时。to_a利用了2.2的另一个答案,但为了相同的结果将其减少了一点。只是在适当的地方切片。哦,这是一个非常简单的方法@丹尼尔波尔弗:很好!你应该把它加到你的答案里。那比我的简单多了!我追求的是名字上的连续跑步。这是步骤4的结果。谢谢你的解释!丹尼尔波尔弗的答案似乎很简单<当{h1,h2 |(h1[:name]!=h2[:name])| |(h1[:end]!=h2[:start])时,代码>切分。有什么不去的理由吗?我不认为有什么理由不去@RyanKing。这比我的有了很大的进步。@RyanKing丹尼尔的回答有一个小问题,我在上面提到了。尽管如此,我还是认为他的方法更好。因此,只要比Daniels的答案先按
start
对数据进行排序,就可以了,对吧?我要的是按名称连续运行。这是步骤4的结果。谢谢你的解释!丹尼尔波尔弗的答案似乎很简单<当{h1,h2 |(h1[:name]!=h2[:name])| |(h1[:end]!=h2[:start])时,代码>切分。有什么不去的理由吗?我不认为有什么理由不去@RyanKing。这比我的有了很大的进步。@RyanKing丹尼尔的回答有一个小问题,我在上面提到了。尽管如此,我仍然认为他的方法更好。因此,只要比Daniels的答案先按
start
对数据进行排序,就可以了,对吗?