基于值的哈希数组上的唯一

时间:2011-01-30 04:40:50

标签: ruby

我觉得这可以改善(红宝石的常见感觉)。我试图根据值来统一一组哈希值。在这个例子中,我想要元素的颜色。苔藓和雪是冒名顶替者。

# remove unique array of hashes based on a hash value

a = [
  { :color => "blue", :name => "water" },
  { :color => "red", :name => "fire" },
  { :color => "white", :name => "wind" },
  { :color => "green", :name => "earth" },
  { :color => "green", :name => "moss" },
  { :color => "white", :name => "snow" }
]

# remove moss and snow
uniques = []
a.each_with_index do |r, i|
  colors = uniques.collect {|e| e[:color]}

  if !colors.include? r[:color]
    uniques.push r
  else
    a[i] = nil
  end
end

a.compact!

puts a

这将打印

{:color=>"blue", :name=>"water"}
{:color=>"red", :name=>"fire"}
{:color=>"white", :name=>"wind"}
{:color=>"green", :name=>"earth"}

这是"正确"但我觉得这太过分了。我对.map .inject的体验是有限的,那些先进的技术让我望而却步。如果有人能够重新考虑这一点,那么我可以帮助我理解另一种简洁的技巧。

3 个答案:

答案 0 :(得分:75)

在Ruby 1.9中,尝试以下

a.uniq! {|e| e[:color] }

答案 1 :(得分:6)

我会使用Array的rejectselect方法:

require 'pp'

a = [
  { :color => "blue", :name => "water" },
  { :color => "red", :name => "fire" },
  { :color => "white", :name => "wind" },
  { :color => "green", :name => "earth" },
  { :color => "green", :name => "moss" },
  { :color => "white", :name => "snow" }
]

pp a.reject{ |h| %w[moss snow].include?( h[:name]) } 
# >> [{:color=>"blue", :name=>"water"},
# >>  {:color=>"red", :name=>"fire"},
# >>  {:color=>"white", :name=>"wind"},
# >>  {:color=>"green", :name=>"earth"}]

或者你可以对此持肯定态度,并select你要保留的那些:

pp a.select{ |h| %w[water fire wind earth].include?( h[:name] ) } 
# >> [{:color=>"blue", :name=>"water"},
# >>  {:color=>"red", :name=>"fire"},
# >>  {:color=>"white", :name=>"wind"},
# >>  {:color=>"green", :name=>"earth"}]

你并没有真正处理哈希,它是一个恰好包含哈希的数组,所以不要让它们混淆你。像rejectselect这样的数组方法是过滤掉不需要的或保持想要的元素的核心方法。

在你的代码示例中,你忽略了你的目标是什么:你想要的元素,拒绝“苔藓”和“雪”,这些都是非元素。过滤掉非元素,并在散列中留下正确/真实的元素。从那里你可以提取正确的颜色。

使用uniq时要注意的另一个问题是,它是位置的,换句话说,它会查找第一个唯一值并拒绝后续值。这在您的代码中并不明显,因为您的数组始终与您测试的顺序相同。如果你拖延订单虽然......:

2.times do
  pp a.shuffle.uniq{ |h| h[:color] }
end

传递#1 ......

# [{:color=>"red", :name=>"fire"},
#  {:color=>"white", :name=>"wind"},
#  {:color=>"green", :name=>"moss"},
#  {:color=>"blue", :name=>"water"}]

传递#2 ......

# [{:color=>"green", :name=>"earth"},
#  {:color=>"blue", :name=>"water"},
#  {:color=>"red", :name=>"fire"},
#  {:color=>"white", :name=>"snow"}]

突然间,即使颜色是独一无二的,我们也看到“苔藓”和“雪”都潜入了结果。这些都是你需要注意的微妙问题。

答案 2 :(得分:1)

对于任何可能需要更短correct answer by Steve Wilhelm 变种

的人

<强>提防

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.Graphics;
public class roomwars extends JPanel implements ActionListener, KeyListener {
    //public JPanel pane;
    public JFrame frame;
    public JButton start, help;
    public JTextField box;
    int x=0, y=0, velx =0, vely =0;
    Timer t = new Timer(5, this);
    public void run(){
        frame = new JFrame("ROOM WARS!");
        frame.setSize(700, 700);
        frame.setVisible(true);
        frame.add(this);
    }
    public void second (){
        t.start();
        addKeyListener(this);
        //setFocusalbe(true);
        //SETFocusTraversalKeyEnabled(false);
    }
    public void paintComponent(Graphics g) {
        Color mypurple = new Color(34, 0, 56);
        g.setColor(mypurple);
        g.fillRect(x, y, 30, 30);
        //g.setColor(Color.PINK);
        //g.fillRect(655,632,30,30);
    }

    public void actionPerformed(ActionEvent e){
        repaint();
        x+= velx;
        y+= vely;
    }

     public void keyPressed(KeyEvent e){
        int code = e.getKeyCode();
        if (code == KeyEvent.VK_UP){
            vely = -1;
            velx = 0;
        }
        else if (code == KeyEvent.VK_DOWN) {
            vely = 1;
            velx = 0;
        }
        else if (code == KeyEvent.VK_RIGHT) {
            velx = -1;
            vely = 0;
        }
        else if (code == KeyEvent.VK_LEFT) {
            velx = 1;
            vely = 0;
        }
    }
    public void keyTyped(KeyEvent e){}
    public void keyReleased(KeyEvent e) {}

    public static void main(String[] args) {
        new roomwars().run();
    }

}
对于哈希数组,

将无法工作,就像

一样
a.uniq!(&:color)

也无效。

有关&amp ;;的更多信息运营商,阅读this linkthis question上的评论,而这些评论又有足够的资源链接。

另一方面,你可以使用lambdas来处理Symbol#to_proc方法,正如here所解释的那样,尽管它可能只是让事情复杂化,当然也不会是正确答案的简短版本。然而,这是非常有趣的知识。

感谢mukesh-kumar-gupta为heads-up