【问题标题】:originals indexes of sorted elements in RubyRuby中排序元素的原始索引
【发布时间】:2013-01-04 22:52:11
【问题描述】:
arr = [1,3,2,4]

arr.sort #=> [1,2,3,4]

我想要一个数组[0, 2, 1, 3]arr.sort 顺序中的原始索引)

Ruby 1.9.3 有没有一种简单的方法来做到这一点?

谢谢

【问题讨论】:

    标签: ruby arrays sorting indexing


    【解决方案1】:
    xs = [1, 3, 2, 4]
    original_indexes = xs.map.with_index.sort.map(&:last)
    #=> [0, 2, 1, 3]
    

    【讨论】:

    • 不知道哪种方案最快
    • 第二行末尾的字符“&”是什么?
    • 我将如何反转排序,即按降序排列的值?
    【解决方案2】:
    arr=[1,3,2,4]
    p arr.map{|e| arr.sort.index(e)}
    

    为了避免每次排序,更好的是:

    arr=[1,3,2,4]
    arr_s = arr.sort
    p arr.map{|e| arr_s.index(e)}
    

    更新

    arr=[1,3,2,4]
    start_time = Time.now
    (1..100000).each do |i|
        arr.map{|e| arr.sort.index(e)}
    end
    elapsed = Time.now - start_time
    p elapsed
    
    xs = [1, 3, 2, 4]
    start_time = Time.now
    (1..100000).each do |i|
        xs.map.with_index.sort.map(&:last)
    end
    elapsed = Time.now - start_time
    p elapsed
    

    得到了结果:

    0.281736
    0.504314
    

    【讨论】:

    • 注意map是O(n),然后排序O(n log n)再索引另一个O(n)。
    • 顺便说一句,with_index 在 1.8.7 中不存在
    【解决方案3】:

    我在 MRI Ruby 2.2.1p85(Mac 和 CentOS 上)上进行了测试,tokland 的解决方案返回了一个错误结果:

    xs = [8,3,2,7,5]
    xs.map.with_index.sort.map(&:last)
    #=> [2, 1, 4, 3, 0] # wrong
    

    Yevgeniy Anfilofyev 解决方案有效,但 支持非唯一数组:

    arr = [8,3,2,7,5]
    arr_s = arr.sort
    arr.map{|e| arr_s.index(e)}
    #=> [4, 1, 0, 3, 2] # correct
    
    arr = [8,3,5,2,8,8,7,5]
    arr_s = arr.sort
    arr.map{|e| arr_s.index(e)}
    #=> [5, 1, 2, 0, 5, 5, 4, 2]
    

    我想出这个:

    arr = [8,3,5,2,8,8,7,5]
    index_order = []
    arr.uniq.sort.each do |a|
      index_order += arr.each_index.select{|i| arr[i] == a }
    end
    r = []
    index_order.each_with_index do |a, i|
      r[a] = i
    end
    r
    #=> [5, 1, 2, 0, 6, 7, 4, 3]
    

    【讨论】:

    • 输入数组[8, 3, 2, 7, 5]的结果[2, 1, 4, 3, 0]怎么错了? a = [8,3,2,7,5] .. b = [a[2],a[1],a[4],a[3],a[0]] ..=> [2,3,5,7,8]
    【解决方案4】:
    array = [6, 20, 12, 2, 9, 22, 17]
    sorted = array.sort
    indices = []
    array.each do |n|
      index = (0...sorted.length).bsearch { |x| n <=> sorted[x] }
      indices << index
    end
    indices
    

    此解决方案适用于 O(nlogn)

    【讨论】:

      【解决方案5】:

      (0..arr.size - 1).sort_by { |i| arr[i] }

      【讨论】:

      • 如果您解释一下 sn-p 正在做什么,这将对提问者有所帮助,以避免延续该网站因宣传而臭名昭著的复制粘贴编程文化
      【解决方案6】:

      一种方法是创建一个与原始数组长度相同的临时数组,其中每个元素都是一对:原始数组的值及其索引。

      例如对于 [1, 3, 2, 4] 它将是 [[1, 0], [3, 1], [2, 2], [4, 3]]

      然后按元素[0]对这个数组进行排序,然后提取元素[1]作为结果。

      像这样:

      def sort_indices(x)
        t = []
        i = -1
        x.map { |e| t << [e, i += 1] }
        t.sort { |a, b| a[0] <=> b[0] }.map{ |a| a[1] }
      end
      
      arr = [ 1, 3, 2, 4]
      sort_indices(arr)
      => [0, 2, 1, 3]
      

      通过将此作为方法添加到 Array 类中,它可以直接在任何数组上调用:

      class Array
        def sort_indices
          t = []
          i = -1
          self.map { |e| t << [e, i += 1] }
          t.sort { |a, b| a[0] <=> b[0] }.map{ |a| a[1] }
        end
      end
      
      p [40, 10, 50, 62, 27].sort_indices
      =>
      [1, 4, 0, 2, 3]
      

      【讨论】:

        猜你喜欢
        • 2013-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多