【问题标题】:ruby reorder array of symbols in one passruby 一次性重新排序符号数组
【发布时间】:2022-01-17 07:58:53
【问题描述】:

我正在寻找最有效的方法来做到这一点。任何带有连字符的东西都必须在数组中任何不带连字符的符号之前。我天真的解决方案过滤数组两次并连接。我觉得应该有一种方法可以一次完成,而不是两次。

input = [:en, :de, :es, :"es-MX", :fr, :ko, :"ko-KR", :"en-GB"]

output = [:"es-MX", :"ko-KR", :"en-GB", :en, :de, :es, :fr]

天真的解决方案:

def reorder(input)
  ## find everything with a hypen
  output = input.select { |l| 
    l.to_s.include?('-')
  }

  # find everything without a hyphen and concat to output
  output.concat(input.reject { |l| 
    l.to_s.include?('-')
  })
end

【问题讨论】:

  • 如果对带和不带连字符的符号顺序没有限制,您可以编写以下内容:[:en, :de, :es, :"es-MX", :fr, :ko, :"ko-KR", :"en-GB"].each_with_object([]) { |sym, arr| sym.to_s.include?('-') ? arr.unshift(sym) : arr << sym } #=> [:"en-GB", :"ko-KR", :"es-MX", :en, :de, :es, :fr, :ko]。我看到这是@Balastrong 答案的变体。

标签: arrays ruby enumerable


【解决方案1】:
input = [:en, :de, :es, :"es-MX", :fr, :ko, :"ko-KR", :"en-GB"]

代码

p input.partition{|x|x.to_s.include?'-'}.flatten

输出

[:"es-MX", :"ko-KR", :"en-GB", :en, :de, :es, :fr, :ko]

【讨论】:

    【解决方案2】:

    这是一种通过数组进行单次传递并保留带连字符的符号顺序和不带连字符的符号顺序的方法。

    def rearrange(arr)
      a = arr.dup
      pos = -1
      a.size.times { |i| a.insert(pos+=1, a.delete_at(i)) if a[i].to_s.include?('-') }
      a
    end
    
    rearrange [:en, :de, :es, :"es-MX", :fr, :ko, :"ko-KR", :"en-GB"]
      #=> [:"es-MX", :"ko-KR", :"en-GB", :en, :de, :es, :fr, :ko]
    

    使用Kernel#dup(以避免改变原始数组)并不构成通过数组,因为(据我了解)C 代码复制内存块。

    【讨论】:

      【解决方案3】:

      您可以使用 Array#partition 一次性过滤数组:

      def reorder(input)
        a, b = input.partition { |l| l.to_s.include?('-') }
      
        a.concat(b)
      end
      

      【讨论】:

      • 我相信这是迄今为止唯一满足单通要求的答案,并且在包含连字符的符号和不包含连字符的符号之间保持顺序。
      【解决方案4】:

      这是一个排序任务,所以对我来说最有意义的是简单地使用Enumerable#sort_by

      # Put symbols with hyphens first
      input.sort_by { |s| s.to_s.include?('-') ? 0 : 1 }
      

      如果您想按这些类别中的其他内容进行排序,您可以执行以下操作:

      # Put symbols with hyphens first, then sort in alphabetical order
      input.sort_by { |s| [s.to_s.include?('-') ? 0 : 1, s] }
      

      【讨论】:

        【解决方案5】:

        怎么样:

        input.sort do |a,b|
          next a <=> b if a.to_s.include?('-') == b.to_s.include?('-')
          a.to_s.include?('-') ? -1 : 1
        end
        

        【讨论】:

          【解决方案6】:

          如我所见,您分两次完成。

          仅通过一次,您可以添加 if 语句并检查每个元素,然后将其推送到 left 数组(如果它包含连字符),否则推送到 right 数组。

          然后连接数组。

          def reorder(input)
            left = []
            right = []
            input.each { |l| 
              if l.to_s.include?('-')
                left.push(l)
              else
                right.push(l)
              end
            }
          
            left.concat(right)
          end
          

          【讨论】:

            猜你喜欢
            • 2011-05-07
            • 2019-10-23
            • 2012-02-29
            • 1970-01-01
            • 1970-01-01
            • 2015-06-20
            • 1970-01-01
            • 1970-01-01
            • 2012-02-14
            相关资源
            最近更新 更多