2017-06-19 184 views
3

我有一个数组。有两种46 s的指数37如何从数组中删除相同元素的元素

arr = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1] 

我得到了一个任务进行排序使用selection sort此阵,但不.sort。结果应该是:

[1, 7, 9, 42, 46, 46, 68, 77, 86, 91] 

所以,我在.rb文件这样做:

def insertion_sort(arr) 
    length = arr.size 
    arr.each_with_index do |number, index| 
    puts "Now the index is #{index}" 
    current_minimum = arr.last(length - index).min 
    puts "Now the current_minimum in last#{length - index} elements is #{current_minimum}" 
    arr.delete(current_minimum) 
    arr.insert(index, current_minimum) 
    end 
end 

arr = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1] 
answer = insertion_sort(arr) 
puts answer.to_s 

我执行该文件,然后得到这个:

[1, 7, 9, 42, 68, 91, 77, 86, 46] 

如果我删除一个46 ,它出来这个:

[1, 7, 9, 42, 46, 68, 77, 86, 91] 

当数组中有多个单个值出现时,我的代码不起作用。当each_with_index块转到索引3时,它将从阵列的其余部分删除所有46

任何人都可以告诉我如何解决这个问题吗?

+2

正如您发现的那样,delete()会删除具有该值的所有元素。你可能想'delete_at(index)'只删除一个元素。 –

+0

谢谢@Mark Thomas。你的回答启发了我。 – Caven

回答

4

要“模拟”这种selection sort,您可以尝试使用从0开始的范围作为索引为0的值并将数组的长度作为最后一个元素对数组进行迭代。此范围不会占用最后一个数组值。

使用each您从创建范围内的每个值,然后,使用“指数”,你可以不考虑的最后一个元素创建一个新的范围,又可以访问但这次领先一步,那就是把1到a的当前值。这样再次使用each您可以从之前创建的“父级”和“子级”范围访问ab

现在,您可以检查是否与数组索引b元素的值大于与数组中的索引a元素的值未成年人,如果此验证为真,则创建的中值temp变量元素位于索引为b的数组中,则位置(索引)b处的数组中的元素将等于位置为a的数组中的元素,最后位于数组中的元素位置为a将等于temp之前创建的变量。

最后返回作为参数传递的数组。

def insertion_sort(array) 
    (0...array.length).each do |a| 
    ((a+1)...array.size).each do |b| 
     if array[b] < array[a] 
     temp  = array[b] 
     array[b] = array[a] 
     array[a] = temp 
     end 
    end 
    end 
    array 
end 

arr = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1] 
p insertion_sort(arr) 
# => [1, 7, 9, 42, 46, 46, 68, 77, 86, 91] 

作为添加@MarkThomas,可以通过用ab索引交换数组值 “跳过” 的temp变量:

def insertion_sort(array) 
    (0...array.length).map do |a| 
    ((a+1)...array.size).each do |b| 
     array[a], array[b] = array[b], array[a] if array[b] < array[a] 
    end 
    end 
    array 
end 
+0

谢谢! @塞巴斯蒂安帕尔马。很好的解决方案,而且你的代码看起来比我的更清晰。 – Caven

+1

你不需要'temp';你可以使用'array [a],array [b] = array [b],array [a]'进行交换。 –

+0

更好,谢谢@MarkThomas。 –

0

感谢大家。我改进了我的代码,看起来工作得很好。下面的代码:

def insertion_sort(arr) 
    length = arr.size 
    arr.each_with_index do |number, index| 

    current_minimum = arr.last(length - index).min 
    current_minimum_index = arr.last(length-index).index(current_minimum) + index # this insure it will delete the right element 
    arr.delete_at(current_minimum_index) 
    arr.insert(index, current_minimum) 

    end 
end 

arr = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1] 

answer = insertion_sort(arr) 
puts "---------------------------------------------------------------" 
puts "Finally we get #{answer.to_s}" 
+0

只从你的问题FYI: “>我有一个任务,使用选择排序”.. 如果任务是寻找选择排序,那么你应该知道,他们正在看你对选择排序的理解算法,而不是代码。您编写的代码不完全是选择排序。为什么名为'insert_sort'的方法? – Surya

+0

@苏里亚,我在学习红宝石,这是我作业的一部分。正如你所说,实际上我的代码不符合[选择排序](https://en.wikipedia.org/wiki/Selection_sort)的定义,例如它应该将特定元素移动到正确的位置,而不是先删除它,然后将其插回到阵列。但是,谢谢你提到这一点。 – Caven

+0

请不要将最终代码添加为答案,除非您打算将其选为真正的答案。 –

0

要在Ruby中实现一个Selection Sort你可以使用Kernel#loop,小心通过objbreak,以获得正确的返回值。

arr = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1] 

sorted = loop.with_object([]) do |_,obj| 
    mindex = arr.index arr.min      #find index of a minimum 
    obj << arr.delete_at(mindex)     #push this minimum value to obj 
    break obj if arr.empty? 
end 

sorted #=> [1, 7, 9, 42, 46, 46, 68, 77, 86, 91] 

更多信息,请参见with_object

+0

我试过你的代码。 'obj'以一个空数组开始。每次从'arr'获取一个最小元素索引时,删除它,然后将其推送到新数组'obj'。当'arr'中的最后一个元素被删除时,循环结束。这种方式创建一个新的数组而不是排序数组。但仍然感谢您的帮助。 @ sagarpandya82 – Caven

+0

@Caven感谢您花时间跟踪我的代码。不幸的是,我误解了选择排序的定义,因此我的代码。 –

+0

@ sagarpandya82没关系,任务的目的不是理解选择排序。它只是想让我对阵列有更好的理解。 – Caven