如何解决了解可枚举模块中的 grep
我非常感谢在我的第一篇堆栈溢出帖子中的任何帮助!
我通常很困惑为什么每次尝试运行我的代码时都会收到空数组。 我正在创建一个方法来过滤“M”的性别并返回它的元素。
我确信有多种方法可以成功运行此代码,但我对使用 grep 及其功能很感兴趣。这是一条捷径,我认为学习它会很好。再次感谢。
students = [
{name: 'John',grade: 8,gender: 'M'},{name: 'Sarah',grade: 12,gender: 'F'},{name: 'Bob',grade: 16,{name: 'Johnny',grade: 2,{name: 'Ethan',grade: 4,{name: 'Paula',{name: 'Donald',grade: 5,{name: 'Jennifer',grade: 13,{name: 'Courtney',grade: 15,{name: 'Jane',grade: 9,gender: 'F'}
]
def is_male(gender)
gender.grep(/M/) { |gend| gend[:gender] }
end
p is_male(students)
解决方法
grep(pattern) → array
grep(pattern) { |obj| block } → array
返回 enum
中每个元素的数组,其中 Pattern === element
。如果提供了可选块,则将每个匹配的元素传递给它,并将块的结果存储在输出数组中。
重要的部分是此方法返回将 Pattern === element
计算为 true
的元素。但是 /M/ === {name: 'John',grade: 8,gender: 'M'}
不返回 true
,对于数组中的所有其他元素也是如此。
因此,您的结果集首先是空的。
块 - 在您的示例中为 { |gend| gend[:gender] }
- 仅在模式匹配时和之后进行评估。该块会更改整个调用的返回值,但不会更改模式匹配的完成方式。
在此上下文中也请注意 Rexgxp#===
的文档。
我正在创建一个方法来过滤“M”的性别并返回其元素。
考虑到上述要求,您的命名似乎具有误导性:
def is_male(gender)
# ...
end
上面看起来像是一个获取性别并检查它是否为男性的方法。我希望是这样的:
is_male('M') #=> true
is_male('F') #=> false
而且 is_male(students)
也不清楚——它是否检查给定数组中是否有男学生?或者如果所有学生都是男性?无论哪种方式,听起来都不像过滤。
让我们首先重命名方法及其参数以更符合您的要求:
def male_students(students)
# ....
end
如果您想使用 grep
,您必须提供一个 模式,它是一个响应 ===
的对象。正则表达式不起作用,因为它对字符串进行操作,而我们的学生是散列(更多内容见下文)。您可以改用 Proc
,它也响应 ===
:
def male_students(students)
is_male = ->(student) { student[:gender] == 'M' }
students.grep(is_male)
end
但使用 select
更容易:
def male_students(students)
students.select { |student| student[:gender] == 'M' }
end
另一种选择是为您的学生使用自定义课程,因为现在您的学生只是散列:
class Student
attr_accessor :name,:grade,:gender
def initialize(name:,grade:,gender:)
@name = name
@grade = grade
@gender = gender
end
def male?
gender == 'M'
end
def female?
gender == 'F'
end
end
现在,相应地更改您的数组:
students = [
Student.new(name: 'John',gender: 'M'),Student.new(name: 'Sarah',grade: 12,gender: 'F'),Student.new(name: 'Bob',grade: 16,Student.new(name: 'Johnny',grade: 2,Student.new(name: 'Ethan',grade: 4,Student.new(name: 'Paula',Student.new(name: 'Donald',grade: 5,Student.new(name: 'Jennifer',grade: 13,Student.new(name: 'Courtney',grade: 15,Student.new(name: 'Jane',grade: 9,]
你可以使用这个非常简单的语法:
students.select(&:male?)
#=>
# [
# #<Student:0x00007fb18d826ce8 @name="John",@grade=8,@gender="M">,# #<Student:0x00007fb18d826b58 @name="Bob",@grade=16,# #<Student:0x00007fb18d826a90 @name="Johnny",@grade=2,# #<Student:0x00007fb18d8269c8 @name="Ethan",@grade=4,# #<Student:0x00007fb18d826838 @name="Donald",@grade=5,@gender="M">
# ]
或 Array
/ Enumerable
中的任何其他有用方法:
students.any?(&:male?) #=> true
students.all?(&:male?) #=> false
students.count(&:male?) #=> 5
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。