- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我是一名 Ruby 新手(4 天前开始,嘿,押韵!)并决定编写一个简单的小工具来娱乐/学习。以下代码是结果。它运行良好,但我非常感谢一些更有经验的 Ruby 开发人员的批评。我正在寻找关于风格、冗长和任何杂项的评论。提示/技巧。
顺便说一下,我对如何重写 lambda 递归更优雅很感兴趣。 (ctrl-f 用于“lambda 递归”)
注意:这不是 Ruby On Rails 项目。这是 Eve Online 的一个小工具。
require 'rubygems'
require 'reve'
require 'yaml'
BASE_SKILLPOINTS = [0, 250, 1414, 8000, 45255, 256000]
def calc_remaining_sp(rank, from_level, to_level)
sp = BASE_SKILLPOINTS.map { |x| x * rank }
[sp[to_level] - sp[from_level], 0].max
end
def summarize_skills(user_id, api_key)
spec = YAML::load(File.open('ukc_skillsets.yaml'))
api = Reve::API.new user_id, api_key
#skill id => general skill info
skills_list = Hash[api.skill_tree.map { |x| [x.type_id, x] }]
api.characters.each { |char|
char_sheet = api.character_sheet :characterID => char.id
puts ""
puts "Character - #{char.name}"
puts "-------------------------------------------------"
char_skills = Hash[skills_list.map { |id, skill| [skill.name, {:level => 0, :remaining_sp => [], :info => skill}] }]
char_sheet.skills.each do |skill|
skill_name = skills_list[skill.id].name
char_skills[skill_name][:level] = skill.level
end
#compute the sp needed for each skill / each level
char_skills.each_pair do |outer_skill_name, *|
#lambda recursion
calc_prereq_sp = lambda do |skill_name|
prereq_remaining_sp = char_skills[skill_name][:info].required_skills.inject(0) do |sum, prereq_skill|
prereq_skill_name = skills_list[prereq_skill.id].name
#call the lambda
calc_prereq_sp.call prereq_skill_name
sum + char_skills[prereq_skill_name][:remaining_sp][prereq_skill.level]
end
current_skill = char_skills[skill_name]
(0..5).each do |target_level|
char_skills[skill_name][:remaining_sp][target_level] =
(calc_remaining_sp current_skill[:info].rank, current_skill[:level], target_level) +
prereq_remaining_sp
end
end
calc_prereq_sp.call outer_skill_name
end
results = {}
spec.each_pair do |skillset_name, *|
process_skillset = lambda do |name|
details = spec[name]
#puts "#{results} , name = #{name}"
if results.include?(name) == false
#puts "#{details['Prerequisites']}"
remaining_sp = 0
remaining_sp += details['Prerequisites'].inject(0) { |sp_remaining, prereq|
process_skillset.call prereq
sp_remaining + results[prereq][:remaining_sp]
} if (details.include? 'Prerequisites') && (details['Prerequisites'] != nil)
details['Required skills'].each_pair { |required_skill, target_level|
remaining_sp += char_skills[required_skill][:remaining_sp][target_level]
} if (details.include? 'Required skills') && (details['Required skills'] != nil)
results[name] = {:remaining_sp => remaining_sp}
end
end
process_skillset.call skillset_name
end
results.reject {|x| (spec[x].include? 'Private') && (spec[x]['Private'] == true)}.to_a().sort_by {|x|x[1][:remaining_sp]} \
.each { |x, y| puts "#{x} = #{y[:remaining_sp]} sp left\n" }
}
end
#userid, apikey hidden for confidentiality
summarize_skills 'xxxxxxx', 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
这是“ukc_skillsets.yaml”的一小段
Basics:
#private = don't show at the end
Private: True
Required skills:
#skill name: skill level
Electronics: 4
Engineering: 4
Weapon Upgrades: 1
Energy Systems Operation: 1
Armor Ship:
Private: True
Prerequisites:
- Basics
Required skills:
Hull Upgrades: 4
Mechanic: 4
......
最佳答案
我注意到的一些事情:
使用 block 时,惯用的做法是对单行使用 { ... }
,对多行使用 do ... end
。您倾向于将它们混为一谈。
if results.include?(name) == false
读起来会比 unless results.include?姓名
if (details.include? 'Prerequisites') && (details['Prerequisites'] != nil)
可以缩短为 if details['Prerequisites']
如果您不明白原因,请阅读 Ruby 中的“真实性”。同样,results.reject {|x| (spec[x].include? 'Private') && (spec[x]['Private'] == true)}
可以变成 results.reject { |x| spec[x]['Private'] }
我认为嵌套的 lambda 情况有点乱,看起来可以提取到几个方法中。不过,如果不进行一些测试,我也不会开始尝试解开它。
尝试使用更具描述性的变量/方法名称。例如,calc_remaining_sp
可以用简单的 remaining_skillpoints
更好地表示。
一般来说,更多行更简洁的代码比更少行数更密集的代码更可取。示例:
results.reject {|x| (spec[x].include? 'Private') && (spec[x]['Private'] == true)}.to_a().sort_by {|x|x[1][:remaining_sp]} \
.each { |x, y| puts "#{x} = #{y[:remaining_sp]} sp left\n" }
这可以重写为:
results.reject! { |skill| spec[skill]['Private'] }
results.sort_by! { |skill| skill[1][:remaining_sp] } # sort_by! requires 1.9 - for 1.8 use results = results.sort_by...
results.each { |x, y| puts "#{x} = #{y[:remaining_sp]} sp left\n" }
最后,当您开始编写更多方法时,请尝试为它们提供易于使用的 API。比如剩余技能点的方法:
def calc_remaining_sp(rank, from_level, to_level)
sp = BASE_SKILLPOINTS.map { |x| x * rank }
[sp[to_level] - sp[from_level], 0].max
end
如果其他人想要使用此方法,他们将不得不记住您在方法名称中使用的缩写以及参数应该出现的顺序,这并不好玩。一个更像 ruby 的替代方案是:
def remaining_skillpoints(options)
skillpoints = BASE_SKILLPOINTS.map { |x| x * options[:rank] }
difference = skillpoints[options[:to]] - skillpoints[options[:from]]
[difference, 0].max
end
这会让另一个 Rubyist 做类似的事情:
points_needed = remaining_skillpoints :rank => 6, :from => 3, :to => 5
或者,使用 Ruby 1.9 中新的 Hash 语法,它可以变得更加令人愉快:
points_needed = remaining_skillpoints rank: 6, from: 3, to: 5
但无论如何,四天后你的表现比我在 Ruby 上的表现要好得多。如果这段代码是您计划在未来构建的东西,我肯定会尝试在您开始重构之前添加一些测试。查看RSpec . Ruby Best Practices 的第 1 章对其进行了很好的介绍。 (免费 PDF)。
享受 Ruby!
关于Ruby 代码评论,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3714473/
我正在使用评论系统,现在,我想重写 url 评论的片段并附加一个符号#,我想将页面部分移动到评论列表,正好是最后一个评论用户,带有 username 我在发表评论时使用 next 重定向用户: {
这个问题在这里已经有了答案: "Rate This App"-link in Google Play store app on the phone (21 个回答) 关闭2年前。 有没有一种方法可以要
长期潜伏者第一次海报... 我们正在使用 Facebook 的 API 将其集成到我们的网络应用程序中,并且我们能够通过 {page-id}/ratings 部分中的 {open_graph_stor
我正在尝试让 Visual Studio 2012 自动格式化我的评论 block ,就像它对我的 C# block 所做的那样。我希望我的评论看起来像这样: /* * Here is my C#
在 MySQl 中创建表时对每个字段进行注释是否会影响性能?我正在处理一个包含 1000 多个表的数据库,几乎每个表中的每个字段都有注释。我只是想知道这是否会以任何方式影响 MySQL 的性能? 最佳
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
这个问题在这里已经有了答案: SQL select only rows with max value on a column [duplicate] (27 个答案) 关闭 5 年前。 我这里有 2
如何在评论中正确编写 --> 或 -->? 我正在维护一个包含许多小程序代码条目的大型 html 文件。说: a --> b. 我在 HTML 中将其编码为 -->: a --> b. 但是,我
这是一个简单的问题。有没有办法允许用户直接在我的应用程序中输入评论和/或评级,并将这些数据发回 Android Market?如果是这样,如果我使用 EditText View 允许用户输入,代码会是
注释是否表示代码中带有//或/* */的注释? 最佳答案 不,注释不是评论。使用语法 @Annotation 将注释添加到字段、类或方法。最著名的注解之一是@Override,用于表示方法正在覆盖父类
我有一个包含两个模型的 Django 应用程序:第一个是 django.contrib.auth.User,第二个是我创建的 Product。 我会为每个产品添加评论,因此每个注册用户都可以为每个产品
有没有办法评论多行......其中已经有一些评论? 即 ... Hello world! Multi-line comment end --> 看来连
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: obj.nil? vs. obj == nil 现在通过 ruby koans 工作,发现这个评论嵌入在
这是一个基本问题 .gemrc 文件中是否允许注释? 如果是,你会怎么做? 我这里查了没用 docs.rubygems.org/read/chapter/11 最佳答案 文档说:The config
有没有办法在 SASS 中添加 sass-only 注释?你知道,所以输出 .css 文件没有那些注释 例如, /* global variables */ $mainColor: #666; /*
我想搜索在任何媒体上发布的评论中的任何特定关键字或几个关键字的组合。我的要求是在 API 的帮助下获取包含该关键字的评论。我浏览了 Instagram API 的文档,发现只能通过哈希标签进行搜索,而
在 WordPress 中,您可以在页面加载之前执行以下操作来编辑文章的内容: add_filter('the_content', 'edit_content'); function edit_con
在指示要合并的内容时, checkin 合并的最佳方法是什么?我已经说过 10 个变更集我正在从我的主分支合并到一个发布分支。每一个都包含我在 checkin 主分支时写的详细注释。现在,当我合并时,
我知道如何查询常规网站的社交参与度计数。可以使用Facebook图形浏览器(https://developers.facebook.com/tools/explorer/)或throug api轻松实
我正在尝试从 YouTube 视频中获得特定评论。例如,我想从 YouTube 视频的第 34 条评论中获取详细信息。有谁知道在不阅读所有评论列表的情况下我该怎么做? 或者,如果没有任何解决方案可以仅
我是一名优秀的程序员,十分优秀!