2015-03-30 44 views
3

允許數組中的某個特定值的最佳方法是什麼?僅允許Ruby數組中的一個特定值

例如,我想允許以下數組中的cat只有一個值:

["dog", "cat", "cat", "hamster", "rabbit", "dog"] 

,使得它返回:

["dog", "cat", "hamster", "rabbit", "dog"] 

編輯:爲不使這個不夠明確道歉,我不是在尋找uniq!我想確保指定的值中只有一個爲

+7

嘗試用[陣列#uniq的](http://ruby-doc.org/core-2.2.0/Array.html# uniq-method) – radubogdan 2015-03-30 19:11:43

+4

問題不清楚。你想刪除重複的「貓」或任何重複? – sawa 2015-03-30 19:24:15

+2

這很有趣。在二讀時,我認爲這個問題非常清楚。然而,在一讀時,我是至少有5位認爲「uniq」被要求的讀者之一。 – 2015-03-30 20:13:36

回答

3

僅做一個價值獨特:

a = ["dog", "cat", "cat", "hamster", "rabbit", "dog"] 

(a.count("cat") - 1).times { a.delete_at(a.index("cat"))} 

#=> ["dog", "cat", "hamster", "rabbit", "dog"] 

這將保留數組中的元素的順序。

要刪除連續項:

使用Enumerable#chunk

a = ["dog", "cat", "cat", "hamster", "rabbit", "dog"] 

a.chunk(&:itself).map(&:first) 

#=> ["dog", "cat", "hamster", "rabbit", "dog"] 

注意,在Ruby中< 2.2,你必須使用chunk{|w| w}因爲itself沒有定義。

+2

乾淨整潔的解決方案! – 2015-03-31 07:12:33

+0

謝謝馬克,很好的解決方案:) – 2015-03-31 08:37:00

0

你需要,可以刪除重複的方法:

require 'set' 

list = ["dog", "cat", "cat", "hamster", "rabbit", "dog"] 

def limit(list, *entries) 
    # Create a tracking table for terms that are limited 
    entries = Hash[entries.to_a.flatten.collect { |i| [ i, 0 ] }] 

    list.select do |i| 
    case (entries[i]) 
    when 0 
     entries[i] += 1 
     i 
    when nil 
     i 
    end 
    end 
end 

puts limit(list, 'cat').inspect 
# => ["dog", "cat", "hamster", "rabbit", "dog"] 

你也可以捲成陣列的一個奇特的子類,這限制了你這一點,但有很多你必須掛鉤添加元素可以添加各種方法。

+1

啊,限於* one *值的一個實例。我會調整。 – tadman 2015-03-30 19:20:01

+1

我不知道你在找什麼:)基於問題和I/O例子,'#uniq'就是答案。美好的一天 – radubogdan 2015-03-30 19:30:50

+1

這似乎是一個衝動的答案。這個問題沒有明確表達他的意圖,因爲這是一個可以接受的解決方案。 – engineersmnky 2015-03-30 19:38:34

1

如果要修改數組中的地方:

def keep_one(arr, obj) 
    i = arr.each_index.find { |i| arr[i] == obj } 
    if i 
    arr.delete(obj) 
    arr.insert(i,obj) 
    end 
end 

arr = ["dog", "cat", "cat", 7.2, { a: 3}, "cat", "dog"] 

a = arr.dup 
keep_one(a,"cat") 
a #=> ["dog", "cat", 7.2, {:a=>3}, "dog"] 

a = arr.dup 
keep_one(a,"dog") 
a #=> ["dog", "cat", "cat", 7.2, {:a=>3}, "cat"] 

a = arr.dup 
keep_one(a,7.2) 
a #=> ["dog", "cat", "cat", 7.2, {:a=>3}, "cat", "dog"] 

a = arr.dup 
keep_one(a,"pig") 
a #=> ["dog", "cat", "cat", 7.2, {:a=>3}, "cat", "dog"] 

如果你不希望修改arr

keep_one(arr.dup,"cat") 
    #=> ["dog", "cat", 7.2, {:a=>3}, "dog"] 
arr 
    #=> ["dog", "cat", "cat", 7.2, {:a=>3}, "dog"] 

def keep_one(arr, obj) 
    found = false 
    arr.each_with_object([]) do |o,a| 
    a << o unless o == obj && found 
    found = true if o == obj 
    end 
end 
1

如果元素的順序,無所謂:

unique_element = "cat" 
animals = ["dog", "cat", "cat", "hamster", "rabbit", "dog"] 
animals << animals.delete(unique_element) if animals.include?(unique_element) 

p animals 
#=> ["dog", "hamster", "rabbit", "dog", "cat"] 

或者,以保持其在一審中的索引:

unique_element = "cat" 
animals = ["dog", "cat", "cat", "hamster", "rabbit", "dog"] 
if animals.include?(unique_element) 
    index_position = animals.index(unique_element) 
    animals.insert(index_position, animals.delete(unique_element)) 
end 

p animals 
#=> ["dog", "cat", "hamster", "rabbit", "dog"] 
+0

我花了一分鐘才明白#1中發生了什麼。 :-) – 2015-03-30 21:35:39

0

嘗試這種情況:

def remove_duplicates(arr, value) 
    index = arr.index(value) 
    index ? (arr - [value]).insert(index, value) : arr 
end 

結果:

irb(main):018:0> remove_duplicates(["dog", "cat", "cat", "hamster", "rabbit", "dog"], "cat") 
=> ["dog", "cat", "hamster", "rabbit", "dog"]                                     
irb(main):019:0> remove_duplicates([1, 1, 2, 2, 3], "cat")                          
=> [1, 1, 2, 2, 3] 
irb(main):020:0> remove_duplicates([1, 1, 2, 2, 3, 4, 5, 2, 1], 2) 
=> [1, 1, 2, 3, 4, 5, 1] 
相關問題