【问题标题】:What could you combine .uniq with to keep the original order of an array?您可以将 .uniq 与什么结合使用以保持数组的原始顺序?
【发布时间】:2021-01-05 17:57:25
【问题描述】:

在使用 Ruby .uniq 方法甚至 .to_set 时,您将如何改变数组的顺序或保持数组的自然顺序?

例如:

([3,4,4,3,6,3]) # =>  [4,6,3])

### with current method my solution outputs:
 
Expected: [4, 6, 3], instead got: [3, 4, 6]

这些是我迄今为止尝试过的所有其他方法:

def solve arr 

#arr.each do |charas| arr << charas unless arr.include?(charas)
#end 
  arr.to_set.to_a
  # arr.uniq
  # arr & arr
  # arr.to_set
  
end

示例测试:

(solve([3,4,4,3,6,3]),[4,6,3])
    Test.assert_equals(solve([1,2,1,2,1,2,3]),[1,2,3])
    Test.assert_equals(solve([1,2,3,4]),[1,2,3,4])
    Test.assert_equals(solve([1,1,4,5,1,2,1]),[4,5,2,1])

【问题讨论】:

  • 你为什么期望4 出现在3 之前?
  • 因为这是数组的原始顺序,也是通过测试的要求。
  • 我在“数组的原始顺序”中看到4 之前的34 之前的3,所以你得到的结果非常好。
  • 我怀疑很多读者理解你的问题。我花了很长时间才弄清楚,我仍然可能是错的。请告诉我我在回答中给出的解释是否正确。无论如何,您需要编辑您的问题以澄清。我还建议您删除对.to_set 的引用,这只会使事情变得混乱。

标签: arrays ruby uniq


【解决方案1】:

您期望什么顺序?你想要他们最后一个索引排列的数字吗?

def solve arr 

#arr.each do |charas| arr << charas unless arr.include?(charas)
#end 
  arr.each_with_object([]) do |element,arr|
    if arr.include?(element)
      arr.delete(element)
      arr<<element
    else
      arr<<element
    end
  end
end
p solve([3,4,4,3,6,3]) # =>  [4,6,3])

【讨论】:

  • 是的,抱歉应该澄清一下。数组中的数字应位于其最后一个位置。我已经用下面的示例测试更新了这个问题——谢谢!
  • arr.inject([]) {|a,e| a.&lt;&lt;(a.delete(e) || e)} 更干净一点,甚至arr.inject([]) {|a,e| a.&lt;&lt;(a.delete(e) {e})}
  • 你是对的!没见过{e}这个表情,有很多东西要学哈哈
【解决方案2】:

我不确定您希望如何获得您所展示的订单。您的问题中可能没有包含代码。无论如何,在 Ruby 2.7.1 上 Array#uniq 肯定会保留原始顺序:

[3,4,4,3,6,3].uniq
#=> [3, 4, 6]

如果您想做一些不同的事情,合乎逻辑的方法可能是使用Enumerable#each_with_index 遍历数组,使用索引以您认为合适的任何方式管理元素的顺序。

【讨论】:

  • 感谢您的详尽回答。虽然我最初使用 arr.uniq 并且它对数组进行了排序,但这有点奇怪。
  • @KobbyAdarkwa 它不对数组进行排序,它保持第一次遇到的顺序。如果你想要最后的遭遇,你将不得不双重反转。 [3,4,4,3,6,3].reverse.uniq.reverse #=&gt; [4,6,3]
【解决方案3】:

使用reverse 两次:在uniq 之前和之后。这:reverse.uniq 返回 原始数组中从最后到第一个出现的唯一元素。第二个reverse 将这些元素按在输入数组中找到的顺序排列:

my_array.reverse.uniq.reverse

例如:

puts [3,4,4,3,6,3].reverse.uniq.reverse.inspect     # => [4, 6, 3]
puts [1,2,1,2,1,2,3].reverse.uniq.reverse.inspect   # => [1, 2, 3]
puts [1,2,3,4].reverse.uniq.reverse.inspect         # => [1, 2, 3, 4]
puts [1,1,4,5,1,2,1].reverse.uniq.reverse.inspect   # => [4, 5, 2, 1]

【讨论】:

  • 不错的一个!此外,如果没有您的回答,我无法弄清楚这个问题。
【解决方案4】:

您似乎想要在 Array 中按最后一个索引排序的唯一元素。

我们可以使用uniqsort_byrindex 来处理这个问题(这将返回给定元素的最后一个索引)

arr = [3,4,4,3,6,3]
arr.uniq.sort_by(&arr.method(:rindex))
#=> [4,6,3]

【讨论】:

  • 有点啰嗦,但我喜欢!
【解决方案5】:

我对这个问题的理解是,如果arr 是给定数组,我们将生成一个数组brr,其中包含arr 的唯一元素,该元素具有以下属性:对于任何两个索引i 和@ 987654326@,0 &lt;= i &lt; j &lt;= brr.size-1arr.rindex(brr[i]) &lt; arr.rindex(brr[j]。其内容为:“arrbrr[i] 的最后一个实例在arrbrr[j] 的最后一个实例之前。

这是一种在一次通过中生成所需数组的方法。

require 'set'
def weird_uniq(arr)
  set = Set.new
  h = arr.reverse_each.with_object([]) { |n,a| a.unshift(n) if set.add?(n) }
end
weird_uniq [3,4,4,3,6,3]
  #=> [4,6,3])
weird_uniq [1,2,1,2,1,2,3]
  #=> [1,2,3]
weird_uniq [1,2,3,4]
  #=> [1,2,3,4]
weird_uniq [1,1,4,5,1,2,1]
  #=> [4, 5, 2, 1] 

Set#add?。集合查找(如哈希键查找)非常快,几乎与集合的大小无关。

【讨论】:

  • 反向迭代和 unshift 是一种创造性的单通道解决方案。虽然我们使用 set 进行查找,为什么不完全利用它arr.inject(Set.new) {|m,e| set.delete(e).add(e)}.to_a?有什么缺点吗?
  • 我多么喜欢红宝石。众所周知的猫有很多选择s.uniq.sort_by(&amp;s.method(:rindex))
  • @engineersmnky,我特别喜欢#2。请修改并取消删除您的答案。让我想想保持秩序的回复.to_a。 (我以为你确实是 Ruby。)
  • #1 看起来也不错。 (那应该是m.delete(e).add(e)。)集合的底层哈希保留键插入顺序这一事实应该确保集合做同样的事情。 ****x2!
  • 是的,我错了。在手机上编写代码和降价并不奇怪,但也许当我回到电脑上时我会进行基准测试。
猜你喜欢
  • 2016-11-19
  • 2010-12-05
  • 2012-08-05
  • 2020-02-06
  • 1970-01-01
  • 2015-04-27
  • 1970-01-01
  • 2015-06-02
  • 1970-01-01
相关资源
最近更新 更多