ruby通过迭代另一个数组来删除重复项并修改嵌套数组中的现有元素
我有一个数组doc\u count,其中包含带有日期(年-月-日)的字符串 我想通过删除“重复项”将文档计数转换为目标,这意味着,我想保留较长的日期字符串,并删除较短的日期字符串,例如 “2019-02-01:186904”而不是“2019-02-01” 由于某些原因,我的尝试未能生成与目标相同的数组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
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
,第一种方法更有效,第二种方法更简单
使用(akamerge!
)的形式,使用块来确定合并的两个散列中存在的键的值
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 }