我觉得这可以改善(红宝石的常见感觉)。我试图根据值来统一一组哈希值。在这个例子中,我想要元素的颜色。苔藓和雪是冒名顶替者。
# 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的体验是有限的,那些先进的技术让我望而却步。如果有人能够重新考虑这一点,那么我可以帮助我理解另一种简洁的技巧。
答案 0 :(得分:75)
在Ruby 1.9中,尝试以下
a.uniq! {|e| e[:color] }
答案 1 :(得分:6)
我会使用Array的reject
或select
方法:
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"}]
你并没有真正处理哈希,它是一个恰好包含哈希的数组,所以不要让它们混淆你。像reject
和select
这样的数组方法是过滤掉不需要的或保持想要的元素的核心方法。
在你的代码示例中,你忽略了你的目标是什么:你想要的元素,拒绝“苔藓”和“雪”,这些都是非元素。过滤掉非元素,并在散列中留下正确/真实的元素。从那里你可以提取正确的颜色。
使用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 link或this question上的评论,而这些评论又有足够的资源链接。
另一方面,你可以使用lambdas来处理Symbol#to_proc方法,正如here所解释的那样,尽管它可能只是让事情复杂化,当然也不会是正确答案的简短版本。然而,这是非常有趣的知识。
感谢mukesh-kumar-gupta为heads-up