我试图从字符串数组中找出如何根据字符比较字符串。例如,有以下几点:
arr = [4, "string", "gnirts", "strign", "ta", "atc"]
在这种情况下,"ta"和"atc"与其他字符串不匹配。但是"字符串","gnirts","strign"匹配。
我的第一个想法是将数组分开,进行长度检查。然后比较字符串并保留第一个礼物。
我知道我不在乎4。它只是指示字符串的数量,所以我可以做一个 arr.shift(1)。
我知道我可以做类似 string.chars.sort 的事情,但是我如何比较数组中的字符串?
我在想这样的事情:
arr.each_with_index do |value, index|
index.each do |item|
if value.chars.sort == item
return value
end
end
这绝对行不通。
我最终想要看到的是在数组上有一个排序,所以我最终会得到 atc、gnirts 和字符串(因为其他人与它匹配并且字符串排在第一位)。
那么,我如何最终比较数组中的字符串并保留第一个字符串呢?
编辑: 输入类似于 [4, "string", "gnirts", "strign", "ta", "atc"] 输出数组将是
["atc", "ta", "string"]
因此,匹配将保留第一个礼物,然后对不匹配的礼物进行排序。
input = [4, "string", "gnirts", "strign", "ta", "atc"]
input.
drop(1).
group_by { |str| str.chars.sort.join }.
values.
map(&:first)
# => ["string", "ta", "atc"]
逐行浏览:
input.
drop(1).
# => ["string", "gnirts", "strign", "ta", "atc"]]
group_by { |str| str.chars.sort.join }.
# => {
# "ginrst" => ["string", "gnirts", "strign"],
# "at" => ["ta"],
# "act" => ["atc"]
# }
values.
# => [
# ["string", "gnirts", "strign"],
# ["ta"],
# ["atc"]
# ]
map(&:first)
# => ["string", "ta", "atc"]
正如 lacostenycoder 提到的,您可能希望反转输出以匹配预期。
可以使用其他 Enumerable 方法(如reduce
、each
等)来做到这一点,但是group_by
更习惯,我建议阅读 Ruby 的 Enumerable 类,因为如果您知道所有可用的方法,您可以使用方法链完成很多工作。
require 'set'
arr.grep(String).uniq { |obj| obj.each_char.to_set }.sort_by(&:size)
#=> ["ta", "atc", "string"]
Array#uniq 的文档指出,"self
按顺序遍历,并保留第一次出现",这意味着,在"string"
、"gnirts"
和"strign"
中,"string"
在数组中具有最小的索引(1
),因此它是uniq
保留的索引。
可以用obj.each_char.sort
替换obj.each_char.to_set
,但如果数组很大,后者的效率会降低。
如果已知只有一个非字符串并且它是数组的第一个元素,请将grep(String)
替换为drop(1)
。