ruby 如何改变数组元素的位置?

q5lcpyga  于 2023-04-05  发布在  Ruby
关注(0)|答案(8)|浏览(142)

我有一个关于如何改变数组元素的索引的问题,这样它就不会出现在第7位,而是在第2位...
有没有一个函数来处理这个问题?

ufj5ltwl

ufj5ltwl1#

没有比这更简单的了:

array.insert(2, array.delete_at(7))
pbossiut

pbossiut2#

irb> a = [2,5,4,6]
=> [2, 5, 4, 6]
irb> a.insert(1,a.delete_at(3))
=> [2, 6, 5, 4]

UPD:伙计们,它与dest〉src一起工作得很好:

a = [0,1,2,3,4]
a.insert 1, a.delete_at(3)
p a  #=>  [0, 3, 1, 2, 4]

a = [0,1,2,3,4]
a.insert 3, a.delete_at(1)
p a  #=>  [0, 2, 3, 1, 4]

你还能期望什么呢?0,2,1,3,4?我不会称之为dest=3

sg24os4d

sg24os4d3#

初学者说明

这些答案很棒。我正在寻找更多关于这些答案如何工作的解释。下面是上面的答案中发生的事情,如何通过值切换元素,以及文档链接。

# 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”值。

文件

v1l68za4

v1l68za44#

如果你想交换的话,最好的方法是:

array = [4, 5, 6, 7]

array[0], array[3] = array[3], array[0]

array # => [7, 5, 6, 4]
0pizxfdo

0pizxfdo5#

如果你不关心数组中其他元素的位置,你可以使用.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。

9cbw7uwe

9cbw7uwe6#

这里的答案并没有涵盖这两种可能的情况。虽然问题处理的是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)

说明

用更少的数字来思考这个问题可能会有所帮助。考虑:

employees = [:bob, :jane, :steve, :tama, :susan]

我想把:jane移到:tama的前面。我看到:jane在位置1,而:tama当前在位置3。我想我会很有效率,并根据我现在知道的正确位置以一行程序的形式完成这一操作:

employees.insert 3, employees.delete_at(1)

这是否达到了我的预期结果?不,:jane:tama之后。

[:bob, :steve, :tama, :jane, :susan]

为什么会发生这种情况?因为数组成员的索引在被删除成员的点之上发生了变化,所以你假设的引用delete_at之前的成员的索引现在已经改变了。要正确地做到这一点,你最好先删除:jane,然后再次查看employees以确定:tama的索引,现在是2而不是3,然后将:jane插入2

rnmwe5a2

rnmwe5a27#

不是更好用途:

irb> a = [2,5,4,6]
#=> [2, 5, 4, 6]
irb> a.insert(1, a.pop)
#=> [2, 6, 5, 4]

1szpjjfi

1szpjjfi8#

如果您正在寻找在数组中上下移动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

相关问题