Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.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通过迭代另一个数组来删除重复项并修改嵌套数组中的现有元素_Ruby - Fatal编程技术网

ruby通过迭代另一个数组来删除重复项并修改嵌套数组中的现有元素

ruby通过迭代另一个数组来删除重复项并修改嵌套数组中的现有元素,ruby,Ruby,我有一个数组doc\u count,其中包含带有日期(年-月-日)的字符串 我想通过删除“重复项”将文档计数转换为目标,这意味着,我想保留较长的日期字符串,并删除较短的日期字符串,例如 “2019-02-01:186904”而不是“2019-02-01” 由于某些原因,我的尝试未能生成与目标相同的数组 2.6.3 (main):0 > my_attempt => [ [0] [ [0] "foo", [1] "2019-02-01

我有一个数组doc\u count,其中包含带有日期(年-月-日)的字符串

我想通过删除“重复项”将文档计数转换为目标,这意味着,我想保留较长的日期字符串,并删除较短的日期字符串,例如

“2019-02-01:186904”而不是“2019-02-01”

由于某些原因,我的尝试未能生成与目标相同的数组

  2.6.3 (main):0 > my_attempt       
  => [
    [0] [
      [0] "foo",
      [1] "2019-02-01: 186904",
      [2] "2019-03-01: 196961",
      [3] "2019-02-01",
      [4] "2019-04-01"
    ],
    [1] [
      [0] "bar",
      [1] "2019-01-01: 8876",
      [2] "2019-04-01: 8694",
      [3] "2019-02-01",
      [4] "2019-04-01"
    ]
  ]

我怎样才能解决这个问题?多谢各位

一种解决方案可以是und的组合

方法#flat_map返回一个新数组,该数组包含为每个元素运行一次block的级联结果和由最大元素数组生成的#max_。您已经使用了#match来检查日期格式,但在本例中,不需要在单独的方法中移动它

solution = doc_count.map do |topic|
  topic.group_by { |s| s[0..9] }.flat_map do 
    |key, values| key.match?(/^\d{4}-\d{2}-\d{2}/) ? [values.max_by(&:size)] : values 
  end.sort.rotate!(-1)
end
最后但并非最不重要的一点是排序和旋转(-1),以获得所需的数组排序顺序

更新:请使用Cary Swoveland的解决方案,这是更好的,他做了非常出色的工作来详细解释这些步骤

doc_count = [
  ["foo", "2019-02-01: 186904", "2019-03-01: 196961", "2019-01-01", 
   "2019-02-01", "2019-03-01", "2019-04-01"],
  ["bar", "2019-01-01: 8876", "2019-04-01: 8694", "2019-01-01",
   "2019-02-01", "2019-03-01", "2019-04-01"]
]
我们可以写信

def doit(doc_count)
  doc_count.map do |arr|
    date_strings, other_strings =
      arr.partition { |s| s.match? /\A\d{4}-\d{2}-\d{2}(?::|\z)/ }
    other_strings + select_dates(date_strings)
  end
end
其中,
select\u dates
是一种尚未构建的方法

单据计数[0]
的计算如下:

arr = doc_count[0]
  #=> ["foo", "2019-02-01: 186904", "2019-03-01: 196961", "2019-01-01",
  #    "2019-02-01", "2019-03-01", "2019-04-01"] 
date_strings, other_strings =
  arr.partition { |s| s.match? /\A\d{4}-\d{2}-\d{2}(?::|\z)/ }
  #=> [["2019-02-01: 186904", "2019-03-01: 196961", "2019-01-01",
  #     "2019-02-01", "2019-03-01", "2019-04-01"], ["foo"]] 
date_strings
  #=> ["2019-02-01: 186904", "2019-03-01: 196961", "2019-01-01",
  #    "2019-02-01", "2019-03-01", "2019-04-01"] 
other_strings
  #=> ["foo"] 
doc\u count
的第二个元素的计算类似。看

现在,我将给出两种方法来构造方法
select_dates
,第一种方法更有效,第二种方法更简单

使用(aka
merge!
)的形式,使用块来确定合并的两个散列中存在的键的值

def select_dates(date_strings)
  date_strings.each_with_object({}) do |s,h|
    h.update(s[0, 10]=>s) { |_,o,n| n.size >= o.size ? n : o }
  end.values
end
有关块变量
\uu
o
n
\u
——一个有效的局部变量——用于第一个块变量,以告知读卡器未在块计算中使用)。对于上面给出的
单据计数[0]

select_dates(date_strings)
  #=> ["2019-02-01: 186904", "2019-03-01: 196961", "2019-01-01",
  #    "2019-04-01"] 
select_dates(date_strings)
  #=> ["2019-03-01: 196961", "2019-02-01: 186904", "2019-04-01",
  #    "2019-01-01"] 
计算如下

 enum = date_strings.each_with_object({})
   #=> #<Enumerator: ["2019-02-01: 186904", "2019-03-01: 196961",
   #   "2019-01-01", "2019-02-01", "2019-03-01", "2019-04-01"
   #                 ]:each_with_object({})> 
a = date_strings.sort_by(&:size)
  #=> ["2019-01-01", "2019-02-01", "2019-03-01", "2019-04-01",
  #    "2019-02-01: 186904", "2019-03-01: 196961"] 
b = a.reverse
  #=> ["2019-03-01: 196961", "2019-02-01: 186904", "2019-04-01",
  #    "2019-03-01", "2019-02-01", "2019-01-01"] 
b.uniq { |s| s[0, 10] }
  #=> ["2019-03-01: 196961", "2019-02-01: 186904", "2019-04-01",
  #    "2019-01-01"] 

对于生成并传递到块的
enum
的前三个元素,
update
的块不起作用,因为合并的两个哈希(
h
{key=>s}
)没有公共密钥。对于第四个元素
(“2019-02-01”)
,它存在于合并的两个散列中,我们按照块比较
h[“2019-02-01”].size=“2019-02-01:186904”。size=>18
“2019-02-01”。size=“10
。由于前者较大,我们将其作为
h
“2019-02-01”
的值。
update
的其余计算结果类似,导致:

h #=>  ["2019-02-01"=>"2019-02-01: 186904",
  #     "2019-03-01"=>"2019-03-01: 196961", "2019-01-01"=>"2019-01-01",
  #     "2019-04-01"=>"2019-04-01" }
最后一步是从该散列中提取值(
h.values

使用

对于上面给出的
单据计数[0]

select_dates(date_strings)
  #=> ["2019-02-01: 186904", "2019-03-01: 196961", "2019-01-01",
  #    "2019-04-01"] 
select_dates(date_strings)
  #=> ["2019-03-01: 196961", "2019-02-01: 186904", "2019-04-01",
  #    "2019-01-01"] 
计算如下

 enum = date_strings.each_with_object({})
   #=> #<Enumerator: ["2019-02-01: 186904", "2019-03-01: 196961",
   #   "2019-01-01", "2019-02-01", "2019-03-01", "2019-04-01"
   #                 ]:each_with_object({})> 
a = date_strings.sort_by(&:size)
  #=> ["2019-01-01", "2019-02-01", "2019-03-01", "2019-04-01",
  #    "2019-02-01: 186904", "2019-03-01: 196961"] 
b = a.reverse
  #=> ["2019-03-01: 196961", "2019-02-01: 186904", "2019-04-01",
  #    "2019-03-01", "2019-02-01", "2019-01-01"] 
b.uniq { |s| s[0, 10] }
  #=> ["2019-03-01: 196961", "2019-02-01: 186904", "2019-04-01",
  #    "2019-01-01"] 
请注意,
Array#uniq
的文档声明,“
self
按顺序遍历,并保留第一个引用。”。表情

sort_by(&:size).reverse
可以用

sort_by { |s| -s.size }

但据报道,我所用的往往更快。

如果
“2019-04-01”
发生在
“2019-04-01:8694”之前怎么办?应该删除哪一个?@PavelMikhailyuk带冒号的字符串应始终保留在数组中,并且应删除仅带日期的字符串。数组中的顺序并不相关。“示例中显示,<代码>目标>代码>行”是由复杂规则排序的:“FoO”在开始和之后的日期。可能不好也不坏,但是考虑首先将日期从非日期分离,然后<代码>非IXDATE +日期。{| a | a.max_by(&:size)}“好吧!艾米丽,你看到卡里的SWOWLAND解决方案了吗?考虑把我接受的答案改为卡里SvoLand。我更喜欢他的解决方案,他做了非常出色的工作,详细解释了所有必要的步骤。解决方案,它要短得多,而且很有效。
sort_by(&:size).reverse
sort_by { |s| -s.size }