在Ruby中将元素重新定位到数组的前面

met*_*ion 19 ruby

即使来自javascript这对我来说看起来很残酷:

irb
>> a = ['a', 'b', 'c']
=> ["a", "b", "c"]
>> a.unshift(a.delete('c'))
=> ["c", "a", "b"]
Run Code Online (Sandbox Code Playgroud)

是否有更清晰的方法将元素放置在数组的前面?

编辑我的实际代码:

if @admin_users.include?(current_user)
  @admin_users.unshift(@admin_users.delete(current_user))
end
Run Code Online (Sandbox Code Playgroud)

Rya*_*pte 16

也许Array#rotate会对你有用:

['a', 'b', 'c'].rotate(-1)
#=> ["c", "a", "b"]
Run Code Online (Sandbox Code Playgroud)

  • 很高兴知道.不幸的是,这不是将最后一个元素放在前面的问题,而是采用任意元素并将其放在前面.我已经更新了我的问题和道歉. (2认同)

Mar*_*mas 15

也许这对你来说更好看:

a.insert(0, a.delete('c'))
Run Code Online (Sandbox Code Playgroud)


Dan*_*ohn 7

这比看起来更棘手.我定义了以下测试:

describe Array do
  describe '.promote' do
    subject(:array) { [1, 2, 3] }

    it { expect(array.promote(2)).to eq [2, 1, 3] }
    it { expect(array.promote(3)).to eq [3, 1, 2] }
    it { expect(array.promote(4)).to eq [1, 2, 3] }
    it { expect((array + array).promote(2)).to eq [2, 1, 3, 1, 2, 3] }
  end
end
Run Code Online (Sandbox Code Playgroud)

sort_by@Duopixel提出的优雅但是[3, 2, 1]可以进行第二次测试.

class Array
  def promote(promoted_element)
    sort_by { |element| element == promoted_element ? 0 : 1 }
  end
end
Run Code Online (Sandbox Code Playgroud)

@tadman使用delete,但这会删除所有匹配的元素,因此第四个测试的输出是[2, 1, 3, 1, 3].

class Array
  def promote(promoted_element)
    if (found = delete(promoted_element))
      unshift(found)
    end

    self
  end
end
Run Code Online (Sandbox Code Playgroud)

我试过用:

class Array
  def promote(promoted_element)
    return self unless (found = delete_at(find_index(promoted_element)))
    unshift(found)
  end
end
Run Code Online (Sandbox Code Playgroud)

但是第三次​​测试失败了,因为delete_at无法处理nil.最后,我决定:

class Array
  def promote(promoted_element)
    return self unless (found_index = find_index(promoted_element))
    unshift(delete_at(found_index))
  end
end
Run Code Online (Sandbox Code Playgroud)

谁知道一个简单的想法promote可能会如此棘手?


小智 6

其他方式:

a = [1, 2, 3, 4]
b = 3

[b] + (a - [b])
=> [3, 1, 2, 4]
Run Code Online (Sandbox Code Playgroud)


tad*_*man 5

如果用"优雅"表示即使以非标准为代价也更具可读性,您总是可以编写自己的方法来增强数组:

class Array
  def promote(value)
    if (found = delete(value))
      unshift(found)
    end

    self
  end
end

a = %w[ a b c ]
a.promote('c')
# => ["c", "a", "b"] 
a.promote('x')
# => ["c", "a", "b"] 
Run Code Online (Sandbox Code Playgroud)

请记住,这只会重新定位值的单个实例.如果数组中有多个,则在删除第一个之前,可能不会移动后续的数组.

  • Ruby on Rails对Ruby核心类有很多扩展,因此它已经成为一种传统.这真的取决于.聪明和*太聪明之间有一个很好的界限.如果你在很多地方执行这项操作,那将是有道理的.如果只有一个,我会坚持你拥有的. (2认同)

Igo*_*gor 5

加上我的两分钱:

array.select{ |item| <condition> } | array
Run Code Online (Sandbox Code Playgroud)

优点:

  • 可以将多个项目移动到数组的前面

缺点:

  • 这将删除所有重复项,除非它是所需的结果。

示例 - 将所有奇数移到前面(并使数组唯一):

data = [1, 2, 3, 4, 3, 5, 1]
data.select{ |item| item.odd? } | data
# Short version:
data.select(&:odd?) | data
Run Code Online (Sandbox Code Playgroud)

结果:

[1, 3, 5, 2, 4]
Run Code Online (Sandbox Code Playgroud)