如何从数组中删除空元素?

341

我有以下数组

cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"]

我想从数组中删除空元素,并希望得到以下结果:

cities = ["Kathmandu", "Pokhara", "Dharan", "Butwal"]

是否有类似于compact的方法可以不使用循环来实现?


4
由于Rails 6现在有了compact_blank方法,因此可能值得更新已接受的答案为@Marian13的答案 - SRack
21个回答

559

有许多方法可以做到这一点,其中之一是使用reject

noEmptyCities = cities.reject { |c| c.empty? }

您还可以使用reject!,它将直接修改cities。如果拒绝了某些内容,则会返回cities作为其返回值,如果没有进行任何拒绝,则会返回nil。如果您不小心使用,这可能会导致问题(感谢ninja08在评论中指出这一点)。


248
如果您喜欢更简洁的写法,可以使用 cities.reject!(&:empty?)。这行代码的作用是从数组中删除所有空字符串,并修改原始数组。 - aNoble
58
为什么不用cities.reject!(&:blank?)呢?empty?是针对数组的。 - Nico
30
blank? 是只有在使用 ActiveSupport 时才能使用的。标准 Ruby 使用的是 String#empty?: http://www.ruby-doc.org/core-1.9.3/String.html#method-i-empty-3F - Michael Kohl
29
rejectжҜ”reject!жӣҙеҘҪпјҢеӣ дёә [].reject!(&:empty?) иҝ”еӣһ nil, [].reject(&:empty?) иҝ”еӣһ []гҖӮ пјҲжіЁпјҡиҜҘеҸҘиҜқи§ЈйҮҠдәҶеңЁRubyзј–зЁӢиҜӯиЁҖдёӯпјҢе»әи®®дҪҝз”ЁrejectиҖҢдёҚжҳҜreject!жқҘйҒҝе…ҚеҮәзҺ°жңӘйў„жңҹзҡ„nilиҝ”еӣһеҖјгҖӮпјү - konyak
19
拒绝使用时要小心!如果对数组没有进行任何更改,拒绝使用会返回nil。如果您希望在未对数组进行更改时返回数组本身,请仅使用reject而不是拒绝使用感叹号。 - Nick Res
显示剩余7条评论

185
1.9.3p194 :001 > ["", "A", "B", "C", ""].reject(&:empty?)

=> ["A", "B", "C"]

14
我更倾向于使用 .reject(&:blank?) 来避免空值。 - ran632
8
@RanGalili 建议使用 blank?,但这是 rails 方法,而此问题涉及纯粹的 ruby - Swaps

116

以下是对我有效的方法:

[1, "", 2, "hello", nil].reject(&:blank?)

输出:

[1, 2, "hello"]

1
在 Ruby 2.3.1 上执行此代码时出现 NoMethodError: "undefined method `blank?' for 1:Fixnum" 的错误。 - Tom
1
@Tom blank? 是一个特定于Rails的方法。在纯Ruby中,它不存在于Array上。你必须使用empty?或编写自己的方法。 - jpgeek
@jpgeek 感谢您的澄清,我之前没有意识到:blank?是Rails特有的。 - Tom
由于出现了 NoMethodError: undefined method empty? for nil:NilClass 错误,因此使用 :blank?:empty? 更好。 - Lane
:blank works better than :empty. Because :empty does not work for nil - KBIIX

65

compact_blank(Rails 6.1+)

如果您正在使用Rails(或独立的ActiveSupport),从6.1版本开始,有一个compact_blank方法可从数组中删除blank值。

它在底层使用Object#blank?来确定项目是否为空白。

["Kathmandu", "Pokhara", "", "Dharan", nil, "Butwal"].compact_blank
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]

[1, "", nil, 2, " ", [], {}, false, true].compact_blank
# => [1, 2, true]

这里有一个指向文档的链接以及一个指向相关PR的链接

还有一种破坏性变体可用。请参见Array#compact_blank!


如果您使用较旧版本的Rails,请检查compact_blank内部实现

它并不是很复杂,可以通过回溯进行。

def compact_blank
  reject(&:blank?)
end

如果您只需要删除nil值,请考虑使用Ruby内置的Array#compactArray#compact!方法。

["a", nil, "b", nil, "c", nil].compact
# => ["a", "b", "c"]

57

在我的项目中,我使用了delete关键字:

cities.delete("")

6
优雅!不幸的是,它没有返回剩余的数组,但相当流畅。 - Kevin
12
Array.delete方法有些违反直觉。它的操作类似于如果存在.delete!()这样的方法。.delete()会以破坏性的方式直接在数组上操作。 - scarver2

46

当我想整理这样的数组时,我使用:

["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - ["", nil]

这将删除所有空白或空值元素。


1
实际上,铁人的答案更好,因为它还会删除与Object#blank?匹配的任何内容,即nil、""、"\n"、" "、"\n\r"等。与被接受的答案不同,它也可以在没有Rails的情况下工作。 - superluminary

29

最明确的

cities.delete_if(&:blank?)

这将同时删除nil和空字符串("")的值。

例如:

cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal", nil]

cities.delete_if(&:blank?)
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]

去除标点并添加冒号后为“城市:如果为空则删除” :D - clapp
2
blank是Ruby或Rails的方法吗? - Arnold Roa
2
@ArnoldRoa 这是一个 Rails 方法。 - PaulMest
1
如果空字符串之间有空格,会怎样? - Steven Aguilar
@StevenAguilar 一个空格被认为是长度为1的字符(因为空格也是一个字符)。" ".blank? => false - phlegx

23

试试这个:

puts ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""]

4
这很巧妙,并且不会返回空值!这是一个很棒的小技巧。 - Sean Larkin
2
["Kathmandu", "Pokhara", " ", "Dharan", "Butwal"] - [""] - 在这种情况下不起作用 - ajahongir
2.0.0-p247 :001 > ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""] => ["Kathmandu", "Pokhara", "Dharan", "Butwal"] 看起来对我来说是有效的。你为什么认为它不起作用呢? - Raels
1
@Raels,在这种情况下,空字符串并不是空的。它内部有一个单独的空格。 - Chandranshu
1
@Chandranshu,我不同意。我将文本复制并粘贴到编辑器中,发现引号之间没有空格,就像你建议的那样。如果有空格,那么减去["", ""]就可以了。superluminary的示例类似,并且也有效。最初的请求是删除“空元素”,而示例空元素在OP中显示为“”。 - Raels

20

使用reject

>> cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].reject{ |e| e.empty? }
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]

14
正如aNoble在上面指出的那样,可以使用reject(&:empty?) - mu is too short
这很好,因为它将删除与Object#empty?匹配的任何元素,例如"\n"、" "、nil、"\n\n\n"等等... - superluminary
什么版本的Ruby/IRB?它在1.8.7-p358、1.9.3-p448和2.0.0-p247中都可以正常工作。 - the Tin Man
5
nil.empty?的意思是检查空值(nil)是否为空。如果尝试在空值上调用empty?方法,会导致程序崩溃(boom),需要立即停止(break)。 - Naveed
2
@AllenMaxwell @Naveed 如果你的数组中有nil元素,请在reject(&:empty?)之前加上compact,例如[nil,'' ] .compact.reject(&:empty?) - scarver2
显示剩余4条评论

14
cities.reject! { |c| c.blank? }

你希望使用blank?而不是empty?的原因是blank可以识别nil,空字符串和空格符。例如:

cities = ["Kathmandu", "Pokhara", " ", nil, "", "Dharan", "Butwal"].reject { |c| c.blank? }

仍将返回:

["Kathmandu", "Pokhara", "Dharan", "Butwal"]

" " 调用 empty? 方法将返回 false,但你可能希望它返回 true

注意: blank? 只能通过Rails访问,Ruby只支持 empty?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接