清洁阵列的阵列,包括零



例如,我有一个数组:

[[nil, nil], [1, 2], [nil, nil], [nil, nil]] 

清洁它的最佳方法是什么?数组必须只有不包含零的数组。清洁后必须是:

[[1,2]]

类似:

[[nil, nil], [1, 2], [nil, nil], [nil, nil]].each {|x| x - [nil]} 

数组上删除 nil元素的方法称为紧凑。但是,对于这种情况,这还不够,因为您有一系列数组。另外,您将需要选择非nil数组,或拒绝nil的数组。您可以轻松地以下面的方式组合两者:

[[nil, nil], [1, 2], [nil, nil], [nil, nil]].reject { |arr| arr.compact.empty? }

这仅在您具有数字或nil s的子阵列时才起作用。如果您的子阵列都包含,例如[1, nil, 2],然后该解决方案将保留整个子数组。

在迭代子阵列上时,可以突变子阵列以删除nil,但是在迭代时可以将其视为实践。但是,这样做的方法是使用compact方法的 bang 版本,该方法突变原始对象:

.reject { |arr| arr.compact!.empty? }

这将服用[[1, 2, nil, 3]]并返回[[1, 2, 3]]

正如Sagarpandya82指出的那样,您也可以使用全部或任何?简单地检查所有内容是否为nil,还是任何内容是nil,而不是删除nils。

回顾:

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]]

假设您仅对2D阵列感兴趣:

仅由nil s组成的子阵列:

arr.reject { |arr| arr.all?(&:nil?) }

RED子阵列由任何nil S组成:

arr.reject { |arr| arr.any?(&:nil?) }
  • compact将从数组中删除nil元素。
  • map将在数组中的每个项目上运行,并通过在数组的项目上应用代码来返回新的数组。请注意,在您的示例中,数组的元素本身是...数组。
  • reject将返回一个新数组,而没有给定代码回答" false"的元素。
  • select将返回一个带有您给定代码'喜欢的元素的新数组(拒绝的相反)。

所以,如果您只想从数组及其子阵列中删除所有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

如果您要删除所有[nil, nil]条目从列表/array

list.reject{|element| element == [nil, nil]}

或更多地是关于选择非nil元素(这实际上是关于浏览代码)

list.select{|element| element != [nil, nil])

这些功能中的大多数都有一个!对应(例如reject!),该功能对定位进行了修改,这意味着您不必分配返回值(例如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 s,这将做到这一点:

[[3, nil], [1, 2], [nil], [nil, 3, 4]].map(&:compact)
  #=> [[3], [1, 2], [], [3, 4]]

如果要从每个元素中删除所有 nil s,然后要删除所有空数组,这将做到这一点:

[[3, nil], [1, 2], [nil], [nil, 3, 4]].map(&:compact).reject(&:empty?)
  #=> [[3], [1, 2], [3, 4]]

我最近在看facets,这是一种提供大量核心红宝石语言扩展的红宝石宝石。

他们给出的示例之一是阵列#recurse方法,我将在下面显示:

arr = ["a", ["b", "c", nil], nil]
arr.recurse{ |a| a.compact! }
#=> ["a", ["b", "c"]]

在您的情况下,这大约是完成工作的一半 - 您还需要删除非空数组。

通过修补核心红宝石方法来工作。这意味着一旦您运行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]]

相关内容

  • 没有找到相关文章

最新更新