代码之家  ›  专栏  ›  技术社区  ›  tcurdt

从地图构建排序的部分

  •  2
  • tcurdt  · 技术社区  · 16 年前

    我有未排序的键值对映射。

    input = {
      "xa" => "xavalue",
      "ab" => "abvalue",
      "aa" => "aavalue",
      "ba" => "bavalue",
    }
    

    现在我想按键对它们进行排序,并按键的第一个字符将它们分组。与此类似:

    output1 = {
      "a" => {
          "aa" => "aavalue",
          "ab" => "abvalue",  
      },
      "b" => {
        "ba" => "bavalue",
      },  
      "x" => {
        "xa" => "xavalue",
      },  
    }
    
    1. 虽然这是相对简单的,但我正在寻找一种简洁的方法来用Ruby表示从输入到输出1的转换。(对于Ruby标准,我的方法可能过于冗长)

    2. 您可能还注意到地图(通常)没有排序。因此,除非手动排序键并包装对映射的访问,否则上述数据结构将无法正常工作。那么,我如何在Ruby中创建一个键序映射呢?还是已经有了?

    3. 如果有序映射方法不那么简单,我将不得不将最终结构更改为如下所示的结构。我再次寻找一些从输入到输出的简洁的Ruby代码。

    .

    output2 = [
      {
        "name" => "a",
        "keys" => [ "aa", "ab" ],
        "values" => [ "aavalue", "abvalue" ],
      },
      {
        "name" => "b",
        "keys" => [ "ba" ],
        "values" => [ "bavalue" ],
      },
      {
        "name" => "x",
        "keys" => [ "xa" ],
        "values" => [ "xavalue" ],
      }
    ]
    
    4 回复  |  直到 16 年前
        1
  •  2
  •   Thiago Arrais    16 年前

    据我所知,Ruby中没有排序散列/映射的概念,因此您仅限于此类型的好的旧数组。您可能需要从以下代码开始:

    output = input.inject({}) { |acc, pair|
      letter = pair.first[0].chr
      acc[letter] ||= {}
      acc[letter][pair.first] = pair.last
      acc
    }.sort
    

    这将为您提供表单中的数据结构

    [ ["a", {"aa"=>"aavalue",
             "ab"=>"abvalue"}],
      ["b", {"ba"=>"bavalue"}],
      ["x", {"xa"=>"xavalue"}]]
    

    通过将组件数组映射成哈希…

    output.map {|pair| {pair.first => pair.last}}
    

    你可以把它变成

    [{"a"=>{"aa"=>"aavalue",
            "ab"=>"abvalue"}},
     {"b"=>{"ba"=>"bavalue"}},
     {"x"=>{"xa"=>"xavalue"}}]
    

    使用类似的映射,您可以到达列出的最后一个表单(输出2):

    output2 = output.map { |pair|
      hash = pair.last
      { 'name' => pair.first,
        'keys' => hash.keys,
        'values' => hash.values }
    }
    
        2
  •  1
  •   community wiki ttepasse    16 年前

    我是一个蟒蛇,但我还是尝试过:

    class Hash
      def clustered
        clustered = Hash.new
        sort.each do | key, value |
          first = key[0,1]
          unless clustered.has_key?(first)
            clustered[first] = Hash.new        
          end
          clustered[first][key] = value
        end
        clustered
      end
    end
    
        3
  •  1
  •   Bkkbrad    16 年前
    output = input.inject({}){ |h, p| k,v=p; (h[k[0..0]] ||= {})[k] = v; h}
    
        4
  •  1
  •   tcurdt    16 年前

    不幸的是,所有答案都不完整。所以我根据蒂亚戈的解决方案提出了这个问题:

    output1 = input.inject({}) { |acc, pair|
      letter = pair.first[0].chr
      acc[letter] ||= {}
      acc[letter][pair.first] = pair.last
      acc
    }.sort
    
    output2 = output1.inject([]) { |acc, pair|
      acc << {
        'name' => pair.first,
        'keys' => pair.last.keys(),
        'values' => pair.last.values()
      }
      acc
    }