Как подсчитать уникальные имена из текстового файла в рубине - PullRequest
0 голосов
/ 26 сентября 2019

Как найти уникальное количество полных имен из файла .txt, с уникальными именами, найденными только один раз в Ruby?

Это первые 10 строк из файла .txt:

    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.

Ответы [ 3 ]

1 голос
/ 26 сентября 2019

Если вы заботитесь только об уникальных предметах, то вам нужен Набор .

Например:

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

Где это берет "чоппированную" версиюкаждой строки (минус символ перевода строки) и помещает ее в набор.

Теперь вы можете получить их все обратно:

names.sort.each do |name|
  puts name
end
1 голос
/ 26 сентября 2019

Я предположил, что это фамилии, которые должны быть уникальными.

Давайте сначала создадим файл.

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 :: foreach , Enumerator # with_index , Enumerator # with_object и Set :: new .Обратите внимание, что enum2 и enum3 могут рассматриваться как составные перечислители .

Первый элемент генерируется с помощью enum3, передается в блок, а переменным блока назначаются значения:

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

line, idx и set являются блочными переменными .Процесс разбиения enum3.next на три составляющие называется декомпозиция массива .См. эту статью для более полного обсуждения этого важного метода.

Теперь выполняется вычисление блока:

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

См. Целое число # четное? и Set # << </a>.При вычислении 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 мы пропускаем эту строку. (Действительно, единственная причина для включения 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". Теперь мы выполняем последний шаг:

arr.size
  #=> 4

1 Хотя write является методом IO, его обычно пишут(и другие IO методы) с Fileкак его получатель.Это допустимо, поскольку File является подклассом IO и, следовательно, наследует методы последнего.Две двоеточия в IO::write означают, что write - это метод класса .Напротив, знак фунта в IO#gets указывает, что gets является методом экземпляра .

0 голосов
/ 26 сентября 2019

Сначала вы должны узнать, что это за имя, а не.Затем вы можете вставить имена в массив, основываясь на том, есть ли у массива это имя.

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

Затем просто подсчитать массив

array.count

...