【问题标题】:Combine hash keys if values are same如果值相同,则合并哈希键
【发布时间】:2013-02-24 14:14:32
【问题描述】:

我需要这样的哈希:

{"10am - 2pm"=>"Sun - Sat", "5pm - 7pm"=>"Sun - Sat"}

并像这样创建一个新的哈希:

{"10am - 2pm, 5pm - 7pm"=>"Sun - Sat"}

如果哈希中的成员之间有任何值相同,我需要组合键并删除重复项。

【问题讨论】:

  • 为什么是哈希?您是否在跟踪每个密钥并需要能够快速访问它?或者,您是否使用哈希作为队列并最终需要遍历它并分别处理每个条目?像这样修改键的味道很像将哈希用作队列,而这正是数组的用途。
  • 既然可以将数组用作 Ruby 哈希中的键,为什么还要将它们组合成一个字符串?
  • @theTinMan,我正在重新格式化从 API 返回的数据。在该数据中,多天将具有相同的操作时间,因此我关闭操作时间以获得一系列天数。当我将原始日期数字转换为带有跨度(Sun - Sat)的日期单词时,我在这里粘贴的结构是进一步发生的事情。

标签: ruby hash inject


【解决方案1】:

可能有一些更简单的东西,也许一个真正聪明的人会带着一些很酷和禅宗般的东西徘徊,但现在这行得通:

hash = {"10am - 2pm"=>"Sun - Sat", "5pm - 7pm"=>"Sun - Sat"}
hash.group_by{ |k,v| v }.each_with_object({}) { |(k,v), h| h[v.map(&:first).join(', ')] = k }

生成:

{ “上午 10 点 - 下午 2 点,下午 5 点 - 晚上 7 点” => “周日 - 周六” }

@muistooshort 提出了一个很好的观点:

既然可以将数组用作 Ruby 哈希中的键,为什么还要将它们组合成一个字符串?

hash.group_by{ |k,v| v }.each_with_object({}) { |(k,v), h| h[v.map(&:first)] = k } { [“上午 10 点 - 下午 2 点”,“下午 5 点 - 晚上 7 点”] => “周日 - 周六” }

【讨论】:

    【解决方案2】:
    h.inject({}) {|r,(k,v)| r[h.select {|_,_v| _v == v}.keys.join(', ')] = v; r}
    

    【讨论】:

      【解决方案3】:

      我不知道 ruby​​ 语法,但我会创建一个新的哈希,其中键是值,值是键,然后将新的哈希再次分组到数组中,现在值是键,键是值:P

      编辑:

      对于那些不赞成投票的人,是的,我不知道 ruby​​,但是试图给出解决问题的想法有什么问题? OP 不必接受我的答案。

      代码如下:

      HashMap<String, String> hash = new HashMap<String, String>();
              HashMap<String, ArrayList> nhash = new HashMap<String, ArrayList>();
              HashMap<String, String> fhash = new HashMap<String, String>();
      
              hash.put("10am - 2pm", "Sun - Sat");
              hash.put("5pm - 7pm", "Sun - Sat");
      
              Iterator it = hash.keySet().iterator();
              while(it.hasNext()){
                  String k =it.next().toString();
                  String v=hash.get(k);
                  if(nhash.get(v)==null){
                      ArrayList a = new ArrayList();
                      nhash.put(v, a);
                      nhash.get(v).add(k);
                  }else{
                      nhash.get(v).add(k);
                  }
              }
      
              Iterator nit = nhash.keySet().iterator();
              while(nit.hasNext()){
                  String k =nit.next().toString();
                  ArrayList v=nhash.get(k);
                      fhash.put(v.toString(), k);
      
              }
      
              System.out.println(fhash);
      

      【讨论】:

      • 老实说,我不知道我的投票逻辑有什么问题,希望能指出。我只是这样做并工作了
      • 是的,看起来很简单,所以显示一些代码,这正是 OP 正在寻找的。​​span>
      • @theTinMan,他说他不懂 ruby​​,所以我们不能指望“一些代码”(
      • 如果你不能用正确的语言回答问题,也许你应该使用伪代码?这种答案真的会让菜鸟感到困惑。或者至少提及您使用的语言!
      【解决方案4】:
      {"10am - 2pm"=>"Sun - Sat", "5pm - 7pm"=>"Sun - Sat"}
      .inject({}){|h, (k, v)|
         _k = h.key(v)
         h.delete(_k)
         h[[*_k, k].join(", ")] = v
         h
      }
      

      【讨论】:

        【解决方案5】:

        我不会对我自己的解决方案进行投票,因为我更改了要求(这实际上帮助了我后来在我的代码中),但这是我最终做的:

        h = {"10am - 2pm"=>"Sun - Sat", "5pm - 7pm"=>"Sun - Sat"}
        h.reduce({}) { |h, (k,v)| (h[v] ||= []) << k; h}.reduce({}) {|h, (k,v)| h[k] = v.join(', '); h}
        # {"Sun - Sat"=>"10am - 2pm, 5pm - 7pm"} 
        

        我不能只调用 invert,因为重复的值会被压缩到新哈希中的一个成员中。所以我在保留每个组件(在一个数组中)的同时进行反转,然后加入该数组以生成我正在寻找的字符串。

        【讨论】:

          猜你喜欢
          • 2014-11-21
          • 2018-06-10
          • 1970-01-01
          • 2020-11-16
          • 1970-01-01
          • 1970-01-01
          • 2018-02-12
          • 1970-01-01
          • 2014-09-14
          相关资源
          最近更新 更多