25

即使来自javascript,这对我来说也很糟糕:

irb
>> a = ['a', 'b', 'c']
=> ["a", "b", "c"]
>> a.unshift(a.delete('c'))
=> ["c", "a", "b"]

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

编辑我的实际代码:

if @admin_users.include?(current_user)
  @admin_users.unshift(@admin_users.delete(current_user))
end
4

9 回答 9

21

也许这对你来说看起来更好:

a.insert(0, a.delete('c'))
于 2012-10-03T22:25:25.270 回答
18

也许Array#rotate会为你工作:

['a', 'b', 'c'].rotate(-1)
#=> ["c", "a", "b"]
于 2012-10-03T18:03:03.080 回答
11

这是一个比看起来更棘手的问题。我定义了以下测试:

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

sort_by@Duopixel 提出的建议很优雅,但[3, 2, 1]可以用于第二次测试。

class Array
  def promote(promoted_element)
    sort_by { |element| element == promoted_element ? 0 : 1 }
  end
end

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

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

    self
  end
end

我尝试使用:

class Array
  def promote(promoted_element)
    return self unless (found = delete_at(find_index(promoted_element)))
    unshift(found)
  end
end

但这在第三次测试中失败了,因为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

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

于 2015-08-12T03:20:19.397 回答
5

如果“优雅”意味着即使以非标准为代价也更具可读性,那么您始终可以编写自己的方法来增强 Array:

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"] 

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

于 2012-10-03T18:14:31.390 回答
5

加上我的两分钱:

array.select{ |item| <condition> } | array

优点:

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

缺点:

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

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

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

结果:

[1, 3, 5, 2, 4]
于 2017-07-25T08:38:30.433 回答
5

其他方式:

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

[b] + (a - [b])
=> [3, 1, 2, 4]
于 2017-11-07T18:20:43.257 回答
4

最后,我认为这是将元素移到前面的最易读的替代方法:

if @admin_users.include?(current_user)
  @admin_users.sort_by{|admin| admin == current_user ? 0 : 1}
end
于 2012-10-04T04:16:33.040 回答
0

如果数组中的所有元素都是唯一的,则可以使用数组算术:

> a = ['a', 'b', 'c']
=> ["a", "b", "c"]
> a -= "c"
=> ["a", "b"]
> a = ["c"] + a
=> ["c", "a", "b"]
于 2017-01-11T20:23:23.700 回答
0

建立在上面:

class Array
  def promote(*promoted)
    self - (tail = self - promoted) + tail
  end
end

[1,2,3,4].promote(5)
=> [1, 2, 3, 4]
[1,2,3,4].promote(4)
=> [4, 1, 2, 3]
[1,2,3,4].promote(2,4)
=> [2, 4, 1, 3]
于 2020-04-21T03:56:58.053 回答