Ruby 从重复的数组元素中删除
从重复的数组元素中删除的最佳方法是什么。 例如,从数组Ruby 从重复的数组元素中删除,ruby,arrays,Ruby,Arrays,从重复的数组元素中删除的最佳方法是什么。 例如,从数组 a = [4, 3, 3, 1, 6, 6] 需要 a = [4, 1] 我的方法对大量元素的处理速度太慢 arr = [4, 3, 3, 1, 6, 6] puts arr.join(" ") nouniq = [] l = arr.length uniq = nil for i in 0..(l-1) for j in 0..(l-1) if (arr[j] == arr[i]) and ( i != j )
a = [4, 3, 3, 1, 6, 6]
需要
a = [4, 1]
我的方法对大量元素的处理速度太慢
arr = [4, 3, 3, 1, 6, 6]
puts arr.join(" ")
nouniq = []
l = arr.length
uniq = nil
for i in 0..(l-1)
for j in 0..(l-1)
if (arr[j] == arr[i]) and ( i != j )
nouniq << arr[j]
end
end
end
arr = (arr - nouniq).compact
puts arr.join(" ")
arr=[4,3,3,1,6,6]
放置arr.join(“”)
名词IQ=[]
l=arr.length
uniq=nil
对于0中的i…(l-1)
对于0中的j..(l-1)
如果(arr[j]==arr[i])和(i!=j)
名词
更复杂但更快的解决方案(O(n)
我相信:)
a=[4,3,3,1,6,6]
ar=[]
add=proc{| to,form | to,无需引入原始数组的单独副本并使用inject:
[4, 3, 3, 1, 6, 6].inject({}) {|s,v| s[v] ? s.merge({v=>s[v]+1}) : s.merge({v=>1})}.select {|k,v| k if v==1}.keys
=> [4, 1]
下面是我对Perl程序员使用的一个解决方案的看法,该解决方案使用散列来累积数组中每个元素的计数:
ary = [4, 3, 3, 1, 6, 6]
ary.inject({}) { |h,a|
h[a] ||= 0
h[a] += 1
h
}.select{ |k,v| v == 1 }.keys # => [4, 1]
如果这很重要的话,它可以在一行上,在地图的行之间明智地使用分号
另一种方式是:
ary.inject({}) { |h,a| h[a] ||= 0; h[a] += 1; h }.map{ |k,v| k if (v==1) }.compact # => [4, 1]
它将select{…}.keys
替换为map{…}.compact
,因此这并不是一个真正的改进,对我来说更难理解。我需要类似的东西,所以测试了几种不同的方法。这些方法都返回一个在原始数组中重复的项目数组:
module Enumerable
def dups
inject({}) {|h,v| h[v]=h[v].to_i+1; h}.reject{|k,v| v==1}.keys
end
def only_duplicates
duplicates = []
self.each {|each| duplicates << each if self.count(each) > 1}
duplicates.uniq
end
def dups_ej
inject(Hash.new(0)) {|h,v| h[v] += 1; h}.reject{|k,v| v==1}.keys
end
def dedup
duplicates = self.dup
self.uniq.each { |v| duplicates[self.index(v)] = nil }
duplicates.compact.uniq
end
end
因此,在这些方法中,Enumerable.dedup算法似乎是最好的:
- 复制原始数组,使其不可变
- 获取uniq数组元素
- 对于每个唯一元素:nil dup数组中的第一个出现
- 压缩结果
如果(array-array.uniq)工作正常就好了!(它不会-它会删除所有内容)@Joe:我仍在试图找到一种更好的方法。肯定有一种方法可以使用inject
,因为你可以简单地证明,你可以用每个做的所有事情都可以用inject
来完成,Enumerable
中的所有方法都是基于每个来完成的。因此,你可以用任何co>来做任何事情Enumerable
方法的组合也可以通过inject
来完成。这是否更具可读性是另一回事。我想把它降低到O(n)的摊销最坏情况步骤复杂性,因为@fl00r已经提供了一个更好的O(n²)解决方案。@Jörg你能给出一些关于O(n)和O(n²)的链接吗Ruby:)@Jörg查看我的提交inject@fl00r:该符号称为Bachmann-Landau符号。我在这里使用的特定上下文称为算法复杂性理论。在StackOverflow上,这两个主题都有很多问题,尽管你最好的选择可能是算法和数据结构教科书或像这样的课程。C实现的count\u by
方法比ruby实现的count\u by.map
在YARV中更快(尽管仍然是相同的“大O”)吗?这是可行的,但请注意这是O(n^2)
,即对于大型数组来说效率非常低(与OP算法的顺序相同)。请参见Jörg的答案以获得有效的答案,但对于小型数组,它将更快[4,3,3,1,6,6]。注入({}){s,v{s.merge(s[v]?{v=>s[v]+1}:{v=>1})。如果v==1},则选择{k,v{k。键
ary = [4, 3, 3, 1, 6, 6]
ary.inject({}) { |h,a|
h[a] ||= 0
h[a] += 1
h
}.select{ |k,v| v == 1 }.keys # => [4, 1]
ary.inject({}) { |h,a| h[a] ||= 0; h[a] += 1; h }.map{ |k,v| k if (v==1) }.compact # => [4, 1]
module Enumerable
def dups
inject({}) {|h,v| h[v]=h[v].to_i+1; h}.reject{|k,v| v==1}.keys
end
def only_duplicates
duplicates = []
self.each {|each| duplicates << each if self.count(each) > 1}
duplicates.uniq
end
def dups_ej
inject(Hash.new(0)) {|h,v| h[v] += 1; h}.reject{|k,v| v==1}.keys
end
def dedup
duplicates = self.dup
self.uniq.each { |v| duplicates[self.index(v)] = nil }
duplicates.compact.uniq
end
end
test_benchmark_integer
user system total real
Enumerable.dups 2.560000 0.040000 2.600000 ( 2.596083)
Enumerable.only_duplicates 6.840000 0.020000 6.860000 ( 6.879830)
Enumerable.dups_ej 2.300000 0.030000 2.330000 ( 2.329113)
Enumerable.dedup 1.700000 0.020000 1.720000 ( 1.724220)
test_benchmark_strings
user system total real
Enumerable.dups 4.650000 0.030000 4.680000 ( 4.722301)
Enumerable.only_duplicates 47.060000 0.150000 47.210000 ( 47.478509)
Enumerable.dups_ej 4.060000 0.030000 4.090000 ( 4.123402)
Enumerable.dedup 3.290000 0.040000 3.330000 ( 3.334401)
..
Finished in 73.190988 seconds.