清理由 nils 组成的数组数组
Cleaning Arrays of Arrays which consist of nils
例如我有一个数组:
[[nil, nil], [1, 2], [nil, nil], [nil, nil]]
最好的清洁方法是什么?数组必须只有不包含 nil 的数组。清洁后必须是:
[[1,2]]
类似于:
[[nil, nil], [1, 2], [nil, nil], [nil, nil]].each {|x| x - [nil]}
删除 nil
个元素的数组方法称为 compact. However, that is not quite enough for this situation because you have an array of arrays. In addition you will want to select the non-nil arrays, or reject nil
的数组。您可以通过以下方式轻松地将两者结合起来:
[[nil, nil], [1, 2], [nil, nil], [nil, nil]].reject { |arr| arr.compact.empty? }
这仅在您有数字子数组或 nil
时才有效。如果您的子数组包含两个,例如[1, nil, 2]
,则此解将保留整个子数组。
可以在迭代子数组时改变子数组以删除 nil
,但可以考虑在迭代时进行变异练习。尽管如此,实现这一点的方法是使用 compact
方法的 bang 版本来改变原始对象:
.reject { |arr| arr.compact!.empty? }
这需要 [[1, 2, nil, 3]]
和 return [[1, 2, 3]]
。
正如 sagarpandya82 指出的那样,您还可以使用 all or any? 方法简单地检查是否所有内容都是 nil
,或者是否有任何内容是 nil
而不是删除 nil
s.
回顾一下:
original_array = [[nil, nil],[1, nil, 2], [1, 2, 3]]
original_array.reject { |arr| arr.all?(:nil) } # returns [[1, nil, 2], [1, 2, 3]]
original_array.reject { |arr| arr.compact.empty? } # returns [[1, nil, 2], [1, 2, 3]]
original_array.reject { |arr| arr.any?(:nil) } # returns [[1, 2, 3]]
original_array.reject { |arr| arr.compact!.empty? } # returns [[1, 2, 3], [1, 2]]
假设您只对二维数组感兴趣,那么:
删除仅由 nil
s 组成的子数组:
arr.reject { |arr| arr.all?(&:nil?) }
删除由任何 nil
s:
组成的子数组
arr.reject { |arr| arr.any?(&:nil?) }
compact
将从数组中删除 nil
个元素。
map
将 运行 遍历数组中的每个项目,并通过在数组的项目上应用代码 return 一个新数组。请注意,在您的示例中 数组的元素 本身就是... Arrays.
reject
将 return 一个没有您给定代码回答 'false' 的元素的新数组。
select
将 return 一个新数组,其中包含您给定代码 'likes' 的元素(与拒绝相反)。
所以如果你只是想从数组及其子数组(但不是子数组)中删除所有nil
s,你可以调用
list = [[1,2], [nil], [1,nil,2]]
list.map(&:compact).reject(&:empty?) #=> [[1,2], [1,2]]
与
相同
compacted_list = list.map do |element|
element.compact
end
non_empty_list = compacted_list.reject do |element|
element.empty?
end
如果您想要从 list/array
中删除所有 [nil, nil]
个条目
list.reject{|element| element == [nil, nil]}
或者如果它更多地是关于选择非 nil 元素(这实际上只是关于意图揭示代码)
list.select{|element| element != [nil, nil])
这些函数中的大多数都有一个 !
对应项(如 reject!
),它在原地 进行修改,这意味着您不必分配return 值(如 new_list = old_list.reject()
)。
似乎对这个问题有不同的解释。
如果按照问题示例的建议,包含一个 nil
的所有元素(数组)仅包含 nil
s,并且要排除这些元素,则这样做:
[[nil, nil], [1, 2], [nil, nil], [nil, nil]].select(&:first)
#=> [!1, 2]]
如果要排除包含至少一个 nil
的所有元素,可以这样做:
[[3, nil], [1, 2], [3, 4, 5, nil]].reject { |a| a.any?(&:nil?) }
#=> [!1, 2]]
如果要从每个元素中删除所有 nil
,将这样做:
[[3, nil], [1, 2], [nil], [nil, 3, 4]].map(&:compact)
#=> [[3], [1, 2], [], [3, 4]]
如果要从每个元素中删除所有 nil
,然后要删除所有空数组,则这样做:
[[3, nil], [1, 2], [nil], [nil, 3, 4]].map(&:compact).reject(&:empty?)
#=> [[3], [1, 2], [3, 4]]
我最近在看 facets,一个 ruby gem,它提供了很多核心 ruby 语言扩展。
他们给出的示例之一是 Array#recurse 方法,我将在下面展示:
arr = ["a", ["b", "c", nil], nil]
arr.recurse{ |a| a.compact! }
#=> ["a", ["b", "c"]]
在你的案例中,这完成了大约一半的工作——你还想删除非空数组。
Facets 通过修补核心 Ruby 方法来工作。这意味着一旦您 运行 require 'facets/array/recurse'
,任何先前定义的 Array#recurse
方法将被覆盖。由于命名冲突的可能性,修补核心方法通常是不明智的。
尽管如此,它仍然是一个有用的方法,并且很容易将其定义为将数组作为参数而不是对 self
的值进行操作。然后,您可以使用它来定义两个共同实现您的目的的方法:
module ArrayUtils
def recurse(array, *types, &block)
types = [array.class] if types.empty?
a = array.reduce([]) do |arr, value|
case value
when *types
arr << recurse(value, *types, &block)
else
arr << value
end
arr
end
yield a
end
def recursive_compact(array)
recurse(array, &:compact)
end
def recursive_remove_nonempty(array)
recurse(array) do |arr|
arr.reject do |x|
x.is_a?(Array) && x.empty?
end
end
end
end
正在测试:
include ArrayUtils
orig = [[nil, nil], [1, 2], [nil, nil], [nil, nil]]
compacted = recursive_compact(orig)
nonempties = recursive_remove_nonempty compacted
puts "original: #{orig.inspect}"
puts "compacted: #{compacted.inspect}"
puts "nonempties: #{nonempties.inspect}"
和运行宁
original: [[nil, nil], [1, 2], [nil, nil], [nil, nil]]
compacted: [[], [1, 2], [], []]
nonempties: [[1, 2]]
例如我有一个数组:
[[nil, nil], [1, 2], [nil, nil], [nil, nil]]
最好的清洁方法是什么?数组必须只有不包含 nil 的数组。清洁后必须是:
[[1,2]]
类似于:
[[nil, nil], [1, 2], [nil, nil], [nil, nil]].each {|x| x - [nil]}
删除 nil
个元素的数组方法称为 compact. However, that is not quite enough for this situation because you have an array of arrays. In addition you will want to select the non-nil arrays, or reject nil
的数组。您可以通过以下方式轻松地将两者结合起来:
[[nil, nil], [1, 2], [nil, nil], [nil, nil]].reject { |arr| arr.compact.empty? }
这仅在您有数字子数组或 nil
时才有效。如果您的子数组包含两个,例如[1, nil, 2]
,则此解将保留整个子数组。
可以在迭代子数组时改变子数组以删除 nil
,但可以考虑在迭代时进行变异练习。尽管如此,实现这一点的方法是使用 compact
方法的 bang 版本来改变原始对象:
.reject { |arr| arr.compact!.empty? }
这需要 [[1, 2, nil, 3]]
和 return [[1, 2, 3]]
。
正如 sagarpandya82 指出的那样,您还可以使用 all or any? 方法简单地检查是否所有内容都是 nil
,或者是否有任何内容是 nil
而不是删除 nil
s.
回顾一下:
original_array = [[nil, nil],[1, nil, 2], [1, 2, 3]]
original_array.reject { |arr| arr.all?(:nil) } # returns [[1, nil, 2], [1, 2, 3]]
original_array.reject { |arr| arr.compact.empty? } # returns [[1, nil, 2], [1, 2, 3]]
original_array.reject { |arr| arr.any?(:nil) } # returns [[1, 2, 3]]
original_array.reject { |arr| arr.compact!.empty? } # returns [[1, 2, 3], [1, 2]]
假设您只对二维数组感兴趣,那么:
删除仅由 nil
s 组成的子数组:
arr.reject { |arr| arr.all?(&:nil?) }
删除由任何 nil
s:
arr.reject { |arr| arr.any?(&:nil?) }
compact
将从数组中删除nil
个元素。map
将 运行 遍历数组中的每个项目,并通过在数组的项目上应用代码 return 一个新数组。请注意,在您的示例中 数组的元素 本身就是... Arrays.reject
将 return 一个没有您给定代码回答 'false' 的元素的新数组。select
将 return 一个新数组,其中包含您给定代码 'likes' 的元素(与拒绝相反)。
所以如果你只是想从数组及其子数组(但不是子数组)中删除所有nil
s,你可以调用
list = [[1,2], [nil], [1,nil,2]]
list.map(&:compact).reject(&:empty?) #=> [[1,2], [1,2]]
与
相同compacted_list = list.map do |element|
element.compact
end
non_empty_list = compacted_list.reject do |element|
element.empty?
end
如果您想要从 list/array
中删除所有[nil, nil]
个条目
list.reject{|element| element == [nil, nil]}
或者如果它更多地是关于选择非 nil 元素(这实际上只是关于意图揭示代码)
list.select{|element| element != [nil, nil])
这些函数中的大多数都有一个 !
对应项(如 reject!
),它在原地 进行修改,这意味着您不必分配return 值(如 new_list = old_list.reject()
)。
似乎对这个问题有不同的解释。
如果按照问题示例的建议,包含一个 nil
的所有元素(数组)仅包含 nil
s,并且要排除这些元素,则这样做:
[[nil, nil], [1, 2], [nil, nil], [nil, nil]].select(&:first)
#=> [!1, 2]]
如果要排除包含至少一个 nil
的所有元素,可以这样做:
[[3, nil], [1, 2], [3, 4, 5, nil]].reject { |a| a.any?(&:nil?) }
#=> [!1, 2]]
如果要从每个元素中删除所有 nil
,将这样做:
[[3, nil], [1, 2], [nil], [nil, 3, 4]].map(&:compact)
#=> [[3], [1, 2], [], [3, 4]]
如果要从每个元素中删除所有 nil
,然后要删除所有空数组,则这样做:
[[3, nil], [1, 2], [nil], [nil, 3, 4]].map(&:compact).reject(&:empty?)
#=> [[3], [1, 2], [3, 4]]
我最近在看 facets,一个 ruby gem,它提供了很多核心 ruby 语言扩展。
他们给出的示例之一是 Array#recurse 方法,我将在下面展示:
arr = ["a", ["b", "c", nil], nil]
arr.recurse{ |a| a.compact! }
#=> ["a", ["b", "c"]]
在你的案例中,这完成了大约一半的工作——你还想删除非空数组。
Facets 通过修补核心 Ruby 方法来工作。这意味着一旦您 运行 require 'facets/array/recurse'
,任何先前定义的 Array#recurse
方法将被覆盖。由于命名冲突的可能性,修补核心方法通常是不明智的。
尽管如此,它仍然是一个有用的方法,并且很容易将其定义为将数组作为参数而不是对 self
的值进行操作。然后,您可以使用它来定义两个共同实现您的目的的方法:
module ArrayUtils
def recurse(array, *types, &block)
types = [array.class] if types.empty?
a = array.reduce([]) do |arr, value|
case value
when *types
arr << recurse(value, *types, &block)
else
arr << value
end
arr
end
yield a
end
def recursive_compact(array)
recurse(array, &:compact)
end
def recursive_remove_nonempty(array)
recurse(array) do |arr|
arr.reject do |x|
x.is_a?(Array) && x.empty?
end
end
end
end
正在测试:
include ArrayUtils
orig = [[nil, nil], [1, 2], [nil, nil], [nil, nil]]
compacted = recursive_compact(orig)
nonempties = recursive_remove_nonempty compacted
puts "original: #{orig.inspect}"
puts "compacted: #{compacted.inspect}"
puts "nonempties: #{nonempties.inspect}"
和运行宁
original: [[nil, nil], [1, 2], [nil, nil], [nil, nil]]
compacted: [[], [1, 2], [], []]
nonempties: [[1, 2]]