【问题标题】:remove too close time elements from a json array从 json 数组中删除太近的时间元素
【发布时间】:2018-01-30 00:18:34
【问题描述】:

我有一个包含时间和数据的 json 对象数组。

基本上,每个元素,都包含如下的时间、id和用户

[
    {
    "id": "abc",
    "ts": "2017-08-17T20:42:12.557229",
    "userid": "seb"
    },
    {
    "id": "def",
    "ts": "2017-08-17T20:42:52.724773",
    "userid": "seb"
    },
    {
    "id": "ghi",
    "ts": "2017-08-17T20:42:53.724773",
    "userid": "matt"
    },
    {
     "id": "jkl",
     "ts": "2017-08-17T20:44:50.557229",
     "userid": "seb"
    },
    {
     "id": "mno",
     "ts": "2017-08-17T20:44:51.724773",
     "userid": "seb"
    },
    {
      "id": "pqr",
      "ts": "2017-08-17T20:50:52.724773",
      "userid": "seb"
    }
]

如果用户 ID 相同,我的目标是删除彼此太近的对象。如果时间差小于 2 秒,我们删除元素。

从列表中,我应该得到列表

[
    {
    "id": "abc",
    "ts": "2017-08-17T20:42:12.557229",
    "userid": "seb"
    },
    {
    "id": "def",
    "ts": "2017-08-17T20:42:52.724773",
    "userid": "seb"
    },
    {
    "id": "ghi",
    "ts": "2017-08-17T20:42:53.724773",
    "userid": "matt"
    },
    {
      "id": "pqr",
      "ts": "2017-08-17T20:50:52.724773",
      "userid": "seb"
    }
]

即使用户 matt 和 seb 的 2 个对象在 2 秒内彼此太近,我们也必须保留元素,因为它不是同一个用户

"ts": "2017-08-17T20:42:52.724773" for seb

"ts": "2017-08-17T20:42:53.724773" for matt

知道如何用 Ruby 编写代码吗?我总是将元素 n 与 n-1 进行比较,并在需要时删除 n-1

【问题讨论】:

  • 到目前为止您尝试了哪些方法,遇到了什么困难?如果您需要一个起点,您有一个 ArrayHash 对象并需要检查 Time 的差异,可以尝试查看这些类以及任何父类或包含的模块的文档,并且看看有没有什么对你有帮助的地方。
  • 如果数组是[{id: "abc", ts: 2017-08-17T20:40:00.0, userid: "seb"}, {id: "def", ts: 2017-08-17T20:40:01.1, userid: "seb"}, {id: "ghi", ts: 2017-08-17T20:40.02.2, userid: "seb"}],期望的返回值是多少?我假设键是符号,所以不需要引号,并且时间是 TimeDateTime 对象,所以引号也不适用。
  • 您想删除 both、id 'jkl' 和 id 'mno' 是否正确?
  • @CarySwoveland 虽然现在 Ruby 可以解析 "key": "value",但我认为这是一个 JSON 字符串。

标签: arrays json ruby


【解决方案1】:
require 'time'

result = []

timestamps = {}

data.each do |item|
  ts = timestamps[item['userid']]  

  if ts.nil? or Time.parse(item['ts']) - Time.parse(ts) > 2
    result.push(item)
    timestamps[item['userid']] = item['ts']
  end
end

puts result

【讨论】:

    【解决方案2】:

    下面的代码呢?

    它会更改记录的顺序,但如果需要,您可以重新排序。

    require 'date'
    
    def time_elapsed_in_seconds(start_time, end_time)
      ((end_time - start_time) * 24 * 60 * 60).to_i
    end
    
    def too_close?(first_time, second_time, threshold = 2)
      time_elapsed_in_seconds(first_time, second_time) < threshold
    end
    
    def datetimes(a, b)
      return [DateTime.parse(a), DateTime.parse(b)]
    end
    
    def should_reject_record?(record, next_record)
      datetimes = datetimes(record[:ts], next_record[:ts])
      record[:userid] == next_record[:userid] && too_close?(*datetimes)
    end
    
    def filter_records(records)
      sorted = records.sort_by{|record| [record[:userid], record[:ts]] }
      sorted.select.with_index do |record, index|
        previous_record = sorted[index-1]
        record == sorted.first || !should_reject_record?(previous_record, record)
      end
    end
    
    records = [
        {
        "id": "abc",
        "ts": "2017-08-17T20:42:12.557229",
        "userid": "seb"
        },
        {
        "id": "def",
        "ts": "2017-08-17T20:42:52.724773",
        "userid": "seb"
        },
        {
        "id": "ghi",
        "ts": "2017-08-17T20:42:53.724773",
        "userid": "matt"
        },
        {
         "id": "jkl",
         "ts": "2017-08-17T20:44:50.557229",
         "userid": "seb"
        },
        {
         "id": "mno",
         "ts": "2017-08-17T20:44:51.724773",
         "userid": "seb"
        },
        {
          "id": "pqr",
          "ts": "2017-08-17T20:50:52.724773",
          "userid": "seb"
        }
    ]
    
    puts filter_records(records)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多