【问题标题】:Making hashes find each other by their values using Ruby使用 Ruby 使散列通过它们的值找到彼此
【发布时间】:2014-07-12 21:30:25
【问题描述】:

我在这个数组中有一对time_tables。有四个time_tables 通过它们的start_location - end_locationstart_date - end_date 以线性方式相互关联。

当第一个time_table 结束时,另一个time_table 开始,依此类推。

我的代码:

arr =   [
      { name: 01, start_date: '2014-04-24 22:03:00', start_location: 'A', end_date: '2014-04-24 22:10:00', end_location: 'B' },
      { name: 05, start_date: '2014-04-24 22:10:00', start_location: 'C', end_date: '2014-04-24 23:10:00', end_location: 'D' },
      { name: 01, start_date: '2014-04-24 17:10:00', start_location: 'X', end_date: '2014-04-24 20:10:00', end_location: 'B' },
      { name: 01, start_date: '2014-04-24 17:10:00', start_location: 'Z', end_date: '2014-04-24 20:10:00', end_location: 'B' },
      { name: 06, start_date: '2014-04-24 20:15:00', start_location: 'B', end_date: '2014-04-24 22:10:00', end_location: 'C' },
      { name: 03, start_date: '2014-04-24 23:15:00', start_location: 'D', end_date: '2014-04-24 00:10:00', end_location: 'E' }
    ]
new_array = []

i = 0
while i <= 5 do
  if arr[i][:end_location] == arr[i+1][:start_location] && arr[i][:start_date] <= arr[i+1][:start_date]
    new_array << arr[i+1]
  end
  i = i + 1
end

这是我想要的结果:

  # My expexpected result will be this:
  #     [
  #     { name: 01, start_date: '2014-04-24 22:03:00', start_location: 'A', end_date: '2014-04-24 22:10:00', end_location: 'B' },
  #    { name: 06, start_date: '2014-04-24 22:15:00', start_location: 'B', end_date: '2014-04-24 22:20:00', end_location: 'C' },
  #    { name: 05, start_date: '2014-04-24 22:20:00', start_location: 'C', end_date: '2014-04-24 23:10:00', end_location: 'D' },
  #    { name: 03, start_date: '2014-04-24 23:15:00', start_location: 'D', end_date: '2014-04-24 00:10:00', end_location: 'E' }
  # 

  ]

但我的算法似乎很糟糕。感谢您为完成这项工作提供的见解。

【问题讨论】:

  • 我不明白。请解释如何确定预期结果的第二个元素 (name: 06) 的开始和结束日期。
  • @CarySwoveland 你好,Cary!试图运行你的电子邮件 ruby​​code,它不会运行:)
  • 嗯。看起来不错,但如果您想发送电子邮件,这是我的姓氏中的名字,dot com。

标签: ruby algorithm logic


【解决方案1】:

您不是真的在寻找最长的线性后续时间表吗?我想通过 cmets 澄清这一点,但我无权发表评论。输入和输出中 B(和 start_location B)的 start_date 的值也存在差异,所以我假设这是一个错误。

考虑到您想找到最长的线性后续时间表,我已经编写了解决方案。

require 'date'

def getLLTT(time_tables)

    longest = []
    time_tables.sort_by! do |time_table|
        DateTime.parse(time_table[:start_date]).to_time
    end

    0.upto(time_tables.size-1) do |i|

        long_for_i = [time_tables[i]]
        0.upto(i-1) do |j|
            j_end_date = DateTime.parse(longest[j][-1][:end_date]).to_time
            i_start_date = DateTime.parse(time_tables[i][:start_date]).to_time
            if j_end_date <= i_start_date 
                if longest[j][-1][:end_location].eql? time_tables[i][:start_location]
                    if longest[j].size + 1 > long_for_i.size
                        long_for_i = longest[j] + [time_tables[i]]
                    end
                end
            end
        end

        longest[i] = long_for_i
    end
    return longest[-1]
end

puts getLLTT(arr)

所以给定输入:

arr =   [
{ name: 01, start_date: '2014-04-24 22:03:00', start_location: 'A', end_date: '2014-04-24 22:10:00', end_location: 'B' },
  { name: 05, start_date: '2014-04-24 22:10:00', start_location: 'C', end_date: '2014-04-24 23:10:00', end_location: 'D' },
  { name: 01, start_date: '2014-04-24 17:10:00', start_location: 'X', end_date: '2014-04-24 20:10:00', end_location: 'B' },
  { name: 01, start_date: '2014-04-24 17:10:00', start_location: 'Z', end_date: '2014-04-24 20:10:00', end_location: 'B' },
  { name: 06, start_date: '2014-04-24 20:15:00', start_location: 'B', end_date: '2014-04-24 22:10:00', end_location: 'C' },
  { name: 03, start_date: '2014-04-24 23:15:00', start_location: 'D', end_date: '2014-04-24 00:10:00', end_location: 'E' }
]

输出将是:

[
{:name=>1, :start_date=>"2014-04-24 17:10:00", :start_location=>"Z", :end_date=>"2014-04-24 20:10:00", :end_location=>"B"}
{:name=>6, :start_date=>"2014-04-24 20:15:00", :start_location=>"B", :end_date=>"2014-04-24 22:10:00", :end_location=>"C"}
{:name=>5, :start_date=>"2014-04-24 22:10:00", :start_location=>"C", :end_date=>"2014-04-24 23:10:00", :end_location=>"D"}
{:name=>3, :start_date=>"2014-04-24 23:15:00", :start_location=>"D", :end_date=>"2014-04-24 00:10:00", :end_location=>"E"}
]

【讨论】:

  • @YoniGeek :它保存到每个索引的最长序列,例如最长 [i] 保存最长到 i 的时间表数组。现在对于外部循环的每个 i,内部循环从 0 迭代到 i-1,找到在“longest[]”中找到的时间表的最长有效序列(其结尾与给定条件下的 i 相关)之前的索引i 然后将其与 i 的时间表相加,并将其存储在“最长 [i]”中。因此,在外循环迭代结束时,“longest[time_tables.size-1]”将保存最长的线性后续时间表,直到最后一个索引。
  • 但是最长的[]数组在哪里填充?一开始是空的,突然得到Timetable-array的内容。还有一个问题:你想在这里做什么:'if long[j].size + 1 > long_for_i.size'
  • 在最长[i] = long_for_i 处填充,外循环的最后一条语句。关于这一点,它检查先前找到的索引 j 的最长数组添加到当前时间表(表 i 处)是否大于迄今为止为索引 i 找到的最长数组。它用于从索引 0 到 i-1 的索引中从之前找到的索引中获取最长的一个,该索引可以与索引 i 处的时间表顺序连接。
  • 很好,对不起,如果我问你很多...我是 Ruby 新手。这个'-1'在这里做什么:“longest[j][-1][:end_date]”不明白:(它是'longest-array'中的最后一项吗?
  • 没问题。是的,-1 获取数组的最后一个元素,-2 获取倒数第二个元素,依此类推。但在那一行中,它获取存储在最长[j] 中的数组的最后一个元素。最长的数组看起来像 [[a,b],[c,f,j]],所以最长 [0] 给出 [a,b],现在最长 [0][-1] 给出 b。但在代码中,它将是时间表,而不是用于示例的 a、b、c 等。
【解决方案2】:

这将通过连续的结束和开始位置“加入”您的时间序列。

 def span x; x[:end_location].ord - x[:start_location].ord; end
 def diff x, y; x[:start_location].ord - y[:start_location].ord; end
 arr = arr.sort_by { |x| [x[:start_location], span(x)] }
 prev = arr[0]
 arr = arr.slice_before { |e|
   prev, prev2 = e, prev
   diff(prev, prev2) != 0
 }.to_a.map(&:first).chunk(&method(:span)).first[1]

例如,我得到

 arr.map { |x| [x[:start_location], x[:end_location] }
 => [["A", "B"], ["B", "C"], ["C", "D"], ["D", "E"]]

【讨论】:

  • 哇...感谢您提供一些想法,但我几乎看不懂一些代码.... :( 这是什么方法:'.ord' 什么是 span-method 和 diff-method ? 在这一行:prev, prev2 = e, prev, 感谢 4 年时间!
  • 男孩,这是我见过的最糟糕的 ruby​​ 代码示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-11
  • 2017-05-04
  • 2021-06-26
  • 2017-08-10
  • 1970-01-01
相关资源
最近更新 更多