繁体   English   中英

如何计算 ruby 中 txt 文件中的唯一名称

[英]How do I count unique names from a txt file in ruby

如何从 a.txt 文件中找到唯一的全名计数,唯一的名称在 Ruby 中只找到一次?

这是 .txt 文件的前 10 行:

    Smith, Kim -- ut
    Voluptatem ipsam et at.
    Marv, Gardens -- non
    Facere et necessitatibus animi.
    McLoughlin, Matt -- consequatur
    Eveniet temporibus ducimus amet eaque.
    Smith, Jen -- pariatur
    Unde voluptas sit fugit.
    Brad, Nick -- et
    Maiores ab officia sed.

如果您只关心独特的物品,那么您想要的是Set

例如:

names = Set.new(File.readlines('names.txt').map(&:chomp))

这需要每行的“chomped”版本(减去换行符)并将其放入集合中。

现在您可以将它们全部取回:

names.sort.each do |name|
  puts name
end

我假设姓氏必须是唯一的。

让我们首先创建文件。

text =<<~END
Smith, Kim
ut Voluptatem ipsam et at.
Marv, Gardens
non Facere et necessitatibus animi.
McLoughlin, Matt
consequatur Eveniet temporibus ducimus amet eaque.
Smith, Jen
pariatur Unde voluptas sit fugit.
Brad, Nick
et Maiores ab officia sed.
END

FName = "test.txt"

File.write(FName, text)
  #=> 239

参见IO::write 1 我们现在读取文件并计算唯一姓氏的数量。

require 'set'

File.foreach(FName).with_index.with_object(Set.new) do |(line, idx),set|
  set << line[/.+(?=,)/] if idx.even?
end.size
  #=> 4

步骤如下。

enum1 = File.foreach(FName)
  #=> #<Enumerator: File:foreach("test.txt")> 
enum2 = enum1.with_index
  #=> #<Enumerator: #<Enumerator: File:foreach("test.txt")>:with_index> 
enum3 = enum2.with_object(Set.new)
  #=> #<Enumerator: #<Enumerator: #<Enumerator: 
  #      File:foreach("test.txt")>:with_index>:with_object(#<Set: {}>)> 

请参阅IO::foreachEnumerator#with_indexEnumerator#with_objectSet::new 请注意,可以将enum2enum3视为复合枚举数

第一个元素由enum3生成,传递给块并且块变量被赋值:

(line, idx),set = enum3.next
  #=> [["Smith, Kim\n", 0], #<Set: {}>] 
line
  #=> "Smith, Kim\n" 
idx
  #=> 0 
set
  #=> #<Set: {}> 

lineidxset块变量 enum3.next分解为三个组件的过程称为数组分解 有关此重要技术的更全面讨论,请参阅本文

现在执行块计算:

idx.even?
  #=> true 
s = line[/.+(?=,)/]
  #=> "Smith" 
set << s
  #=> #<Set: {"Smith"}> 

看到整数#偶数? 设置#<< 在计算s时, Sting#[]方法的(第三种形式)与正则表达式/.+(?=,)/使用,其内容为“匹配一个或多个字符后跟逗号, (?=,)是一个积极的前瞻性

第二个元素由enum3生成,传递给块,块变量被赋值并执行块计算:

(line, idx),set = enum3.next
  #=> [["ut Voluptatem ipsam et at.\n", 1], #<Set: {"Smith"}>] 
line
  #=> "ut Voluptatem ipsam et at.\n" 
idx
  #=> 1 
set
  #=> #<Set: {"Smith"}> 
idx.even?
  #=> false 

自从idx.even? #=> false idx.even? #=> false我们跳过这一行。 (确实,包含with_index的唯一原因是确定哪些行具有偶数索引。)第三个元素由enum3生成,传递给块,为块变量赋值并执行块计算:

(line, idx),set = enum3.next
  #=> [["Marv, Gardens\n", 2], #<Set: {"Smith"}>] 
line
  #=> "Marv, Gardens\n" 
idx
  #=> 2 
set
  #=> #<Set: {"Smith"}> 
idx.even?
  #=> true 
s = line[/.+(?=,)/]
  #=> "Marv" 
set << s
  #=> #<Set: {"Smith", "Marv"}> 

依此类推,直到我们获得:

arr = File.foreach(FName).with_index.with_object(Set.new) do |(line, idx),set|
  set << line[/.+(?=,)/] if idx.even?
end
  #=> #<Set: {"Smith", "Marv", "McLoughlin", "Brad"}>

请注意,由于集合包含唯一值,因此在处理"Smith, Jen"时不会将"Smith"添加到集合中。 我们现在执行最后一步:

arr.size
  #=> 4

1 尽管writeIO的一种方法,但习惯上以File作为其接收者来编写它(以及其他IO方法)。 这是允许的,因为FileIO的子类,因此继承了后者的方法。 IO::write中的两个冒号表示writeclass 方法 相比之下, IO#gets中的井号表示gets是一个实例方法

您首先必须找出什么是名称而不是名称。 然后,您可以根据数组是否已经具有该名称将名称推送到数组中。

array.push(name) unless array.include?(name)

然后只需对数组进行计数

array.count

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM