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

时间:2019-09-26 17:10:59

标签: ruby file unique counter

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

这是.txt文件的前10行:

<!DOCTYPE html>
<html lang="en">
  <head>
  </head>

  <body class="bg-dark">
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
      <a class="navbar-brand" href="/"></a>
      <button class="navbar-toggler navbar-dark border-0" type="button" data-toggle="collapse" data-target="#nav-content" aria-controls="nav-content" aria-expanded="false" aria-label="Toggle navigation menu">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse justify-content-end" id="nav-content">
        <ul class="navbar-nav align-items-center">
          <li class="nav-item ">
          </li>
          <li class="nav-item ">
          </li>
          <li class="nav-item">
          </li>
          <li class="nav-item">
          </li>
          <li class="nav-item ">
          </li>
        </ul>
      </div>
    </nav>

    <main>
      <div class="container-fluid h-100">
        <div id="map" class="h-100"></div>
      </div>
    </main>

    <footer>
    </footer>
  </body>
</html>

3 个答案:

答案 0 :(得分:1)

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

例如:

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

将每行的“切碎”版本(减去换行符)放入集合中。

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

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

答案 1 :(得分:1)

我假设这是姓氏,必须唯一。

首先创建文件。

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分成三个部分的过程称为array decomposition。有关这项重要技术的完整讨论,请参见this article

现在可以执行块计算:

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

请参见Integer#even?Set#<<。在计算s时,方法Sting#[](的第三种形式)与正则表达式/.+(?=,)/一起使用,该表达式为“匹配一个或多个字符,后跟一个逗号{{1 }}是正向超前

第二个元素由(?=,)生成,传递给块,为块变量分配值并执行块计算:

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的唯一原因是要确定哪些行具有偶数索引。)第三个元素由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"添加到集合中。现在,我们执行最后一步:

"Smith, Jen"

1即使arr.size #=> 4 write的一种方法,习惯上也以IO作为接收者来写它(和其他IO方法)。这是允许的,因为FileFile的子类,因此继承了后者的方法。 IO中的两个冒号表示IO::write class方法。相反,write中的井号表示IO#gets instance方法

答案 2 :(得分:0)

首先,您必须找出名字而不是名字。然后,您可以根据数组中是否已有该名称将其推入数组。

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

然后只对数组进行计数

array.count