【发布时间】:2011-01-19 10:05:06
【问题描述】:
我有一个关于如何更改数组元素的索引的问题,这样它就不会出现在第 7 位,而是在第 2 位...
有处理这个的函数吗?
【问题讨论】:
我有一个关于如何更改数组元素的索引的问题,这样它就不会出现在第 7 位,而是在第 2 位...
有处理这个的函数吗?
【问题讨论】:
没有比这更简单的了:
array.insert(2, array.delete_at(7))
【讨论】:
irb> a = [2,5,4,6]
=> [2, 5, 4, 6]
irb> a.insert(1,a.delete_at(3))
=> [2, 6, 5, 4]
【讨论】:
这些答案很棒。我一直在寻找有关这些答案如何工作的更多解释。以下是上述答案中发生的情况、如何按值切换元素以及文档链接。
# sample array
arr = ["a", "b", "c", "d", "e", "f", "g", "h"]
# suppose we want to move "h" element in position 7 to position 2 (trekd's answer)
arr = arr.insert(2, arr.delete_at(7))
=> ["a", "b", "h", "c", "d", "e", "f", "g"]
这是因为arr.delete_at(index) 删除了指定索引处的元素(在我们上面的示例中为“7”),并返回该索引中的值。因此,运行 arr.delete_at(7) 会产生:
# returns the deleted element
arr.delete_at(7)
=> "h"
# array without "h"
arr
=> ["a", "b", "c", "d", "e", "f", "g"]
把它们放在一起,insert 方法现在将把这个“h”元素放在位置 2。为了清楚起见,把它分成两个步骤:
# delete the element in position 7
element = arr.delete_at(7) # "h"
arr.insert(2, element)
=> ["a", "b", "h", "c", "d", "e", "f", "g"]
假设您想将数组中值为“h”的元素移动到位置 2,而不管其位置如何。这可以通过 index 方法轻松完成:
arr = arr.insert(2, arr.delete_at( arr.index("h") ))
注意:以上假设数组中只有一个“h”值。
【讨论】:
如果你想交换最好的方法:
array = [4, 5, 6, 7]
array[0], array[3] = array[3], array[0]
array # => [7, 5, 6, 4]
【讨论】:
如果您不关心数组中其他元素的位置,您可以使用 .rotate! (请注意,此方法末尾的 ! 会更改实际数组)方法。
arr = [1, 2, 3, 4, 5, 6, 7, 8]
arr.rotate! -3
arr = [6, 7, 8, 1, 2, 3, 4, 5]
这会获取位于索引 7 处的元素 8,并将其旋转到索引 2。
【讨论】:
此处的答案并未涵盖两种可能的情况。虽然该问题处理的origin 索引高于destination,但如果相反,则以下解决方案将不起作用:
array.insert 7, array.delete_at(2)
这是因为删除 2 处的值会使数组中的所有内容(大于 2)向下移动 1。现在我们的目标索引 7 指向以前的索引 8。
要解决这个问题,我们需要检查origin 是否小于destination,如果是,则从destination 中减去1。
origin = 2
destination = 7
destination -= 1 if origin < destination
array.insert destination, array.delete_at(origin)
【讨论】:
不更好用:
irb> a = [2,5,4,6]
#=> [2, 5, 4, 6]
irb> a.insert(1, a.pop)
#=> [2, 6, 5, 4]
?
【讨论】:
如果您正在寻找在数组中上下移动 uniq 项的解决方案:
module ArrayElementMove
MustBeUniqArray = Class.new(StandardError)
ItemNotInArray = Class.new(StandardError)
def self.up!(array, item)
self.check_if_uniq!(array)
return array if array.first == item
position = array.index(item) || raise(ItemNotInArray)
array.insert((position - 1), array.delete_at(position))
end
def self.down!(array, item)
self.check_if_uniq!(array)
return array if array.last == item
position = array.index(item) || raise(ItemNotInArray)
array.insert((position + 1), array.delete_at(position))
end
def self.check_if_uniq!(array)
raise MustBeUniqArray if array.size != array.uniq.size
end
end
规格:
require 'spec_helper'
RSpec.describe ArrayElementMove do
let(:arr) { [1,2,3,4,5,6] }
it do
ArrayElementMove.up!(arr, 4)
expect(arr).to eq([1,2,4,3,5,6])
expect(ArrayElementMove.up!(arr, 4).to eq([1,4,2,3,5,6])
expect(arr).to eq([1,4,2,3,5,6])
ArrayElementMove.up!(arr, 4)
expect(arr).to eq([4,1,2,3,5,6])
ArrayElementMove.up!(arr, 4)
expect(arr).to eq([4,1,2,3,5,6])
end
it do
ArrayElementMove.down!(arr, 4)
expect(arr).to eq([1,2,3,5,4,6])
expect(ArrayElementMove.down!(arr, 4)).to eq([1,2,3,5,6,4])
expect(arr).to eq([1,2,3,5,6,4])
expect(ArrayElementMove.down!(arr, 4)).to eq([1,2,3,5,6,4])
expect(arr).to eq([1,2,3,5,6,4])
end
context 'when non uniq array' do
let(:arr) { [1,4,2,3,4,5,6] }
it do
expect { ArrayElementMove.down!(arr, 3) }.to raise_exception(ArrayElementMove::MustBeUniqArray)
expect(arr).to eq([1,4,2,3,4,5,6])
end
it do
expect { ArrayElementMove.down!(arr, 3) }.to raise_exception(ArrayElementMove::MustBeUniqArray)
expect(arr).to eq([1,4,2,3,4,5,6])
end
end
context 'when non existing item' do
it do
expect { ArrayElementMove.up!(arr, 9) }.to raise_exception(ArrayElementMove::ItemNotInArray)
expect(arr).to eq([1,2,3,4,5,6])
end
it do
expect { ArrayElementMove.up!(arr, 9) }.to raise_exception(ArrayElementMove::ItemNotInArray)
expect(arr).to eq([1,2,3,4,5,6])
end
end
end
【讨论】: