Как подсчитать количество экземпляров определенных слов в абзаце? - PullRequest
1 голос
/ 16 декабря 2011

Я хотел бы посчитать, сколько раз набор слов появляется в каждом абзаце в текстовом файле.Я могу подсчитать, сколько раз набор слов появляется во всем тексте.

Мне предложили, что мой код действительно глючит, поэтому я просто спрошу, что я хотел бы сделатьи, если хотите, вы можете взглянуть на код, который у меня есть внизу.

Итак, учитывая, что в файле "quency_count.txt "есть слова" яблочная груша, дыня, киви ", я хочу знатькак часто слово «яблоко» отображается в каждом абзаце отдельного файла «test_essay.txt», как часто отображается груша и т. д., а затем эти числа выводятся в виде последовательности строк, каждая из которых соответствуетабзац.

Например:

apple, pear, grape, melon, kiwi
3,5,2,7,8
2,3,1,6,7
5,6,8,2,3

Где каждая строка соответствует одному из абзацев.

Я очень, очень новичок в Ruby, поэтому спасибо за ваше терпение.

output_file = '/Users/yirenlu/Quora-Personal-Analytics/weka_input6.csv'
o = File.open(output_file, "r+")

common_words = '/Users/yirenlu/Quora-Personal-Analytics/frequency_count.txt'
c = File.open(common_words, "r")

c.each_line{|$line1|
    words1 = $line1.split
    words1.each{|w1|
        the_file = '/Users/yirenlu/Quora-Personal-Analytics/test_essay.txt'
        f = File.open(the_file, "r")
        rows = File.readlines("/Users/yirenlu/Quora-Personal-Analytics/test_essay.txt")
        text = rows.join
        paragraph = text.split(/\n\n/)
        paragraph.each{|p|
            h = Hash.new
            puts "this is each paragraph"
            p.each_line{|line|
                puts "this is each line"
                words = line.split
                words.each{|w|
                    if w1 == w
                        if h.has_key?(w)
                            h[w1] = h[w1] + 1
                        else
                            h[w1] = 1
                        end
                        $x = h[w1]
                    end
                }
            }
            o.print "#{$x},"
        }
    }
    o.print "\n"
    o.print "#{$line1}"
}

Ответы [ 6 ]

1 голос
/ 16 декабря 2011

Это может быть короче и проще для чтения, если вы используете:

  1. Библиотека CSV.
  2. Более функциональный подход с использованием карты и блоков.
require 'csv'

common_words = %w(apple pear grape melon kiwi)
text = File.open("test_essay.txt").read

def word_frequency(words, text)
  words.map { |word| text.scan(/\b#{word}\b/).length }
end

CSV.open("file.csv", "wb") do |csv|
  paragraphs = text.split /\n\n/
  paragraphs.each do |para| 
    csv << word_frequency(common_words, para)
  end
end

Обратите внимание, что в настоящее время учитывается регистр, но это небольшая корректировка, если вы хотите регистр не учитывается.

1 голос
/ 16 декабря 2011

Вот два однострочных для вычисления частоты слов в строке.

Первый немного легче понять, но он менее эффективен:

txt.scan(/\w+/).group_by{|word| word.downcase}.map{|k,v| [k, v.size]}
# => [['word1', 1], ['word2', 5], ...]

Второйрешение:

txt.scan(/\w+/).inject(Hash.new(0)) { |hash, w| hash[w.downcase] += 1; hash}
# => {'word1' => 1, 'word2' => 5, ...}
1 голос
/ 16 декабря 2011

Если вы привыкли к PHP или Perl, у вас может сложиться впечатление, что переменная типа $line1 является локальной, но это глобальная переменная. Их использование крайне не рекомендуется, и количество случаев, когда они строго необходимы, очень мало. В большинстве случаев вы можете просто пропустить $ и использовать переменные таким образом с надлежащей областью видимости.

Этот пример также страдает от почти нечитаемого отступа, хотя, возможно, это был артефакт процедуры вырезания и вставки.

Обычно для счетчиков требуется создать хэш с нулевым значением по умолчанию, а затем добавить к нему при необходимости:

# Create a hash where the default values for each key is 0
counter = Hash.new(0)

# Add to the counters where required
counter['foo'] += 1
counter['bar'] += 2

puts counter['foo']
# => 1
puts counter['baz']
# => 0

У вас, в основном, есть то, что вам нужно, но все запутано и просто нужно лучше организовать.

0 голосов
/ 16 декабря 2011

Вот альтернативный ответ, который был подправлен для краткости (хотя не так легко читается, как мой другой ответ).

require 'csv'

words = %w(apple pear grape melon kiwi)
text = File.open("test_essay.txt").read

CSV.open("file.csv", "wb") do |csv|
  text.split(/\n\n/).map {|p| csv << words.map {|w| p.scan(/\b#{w}\b/).length}}
end

Я предпочитаю немного более длинный, но более самодокументированный код, нозабавно видеть, насколько маленьким это может стать.

0 голосов
/ 16 декабря 2011

Что по этому поводу:

# Create an array of regexes to be used in `scan' in the loop.
# `\b' makes sure that `barfoobar' does not match `bar' or `foo'.
p word_list = File.open("frequency_count.txt"){|io| io.read.scan(/\w+/)}.map{|w| /\b#{w}\b/}
File.open("test_essay.txt") do |io|
    loop do
        # Add lines to `paragraph' as long as there is a continuous line
        paragraph = ""
        # A `l.chomp.empty?' becomes true at paragraph border
        while l = io.gets and !l.chomp.empty?
            paragraph << l
        end
        p word_list.map{|re| paragraph.scan(re).length}
        # The end of file has been reached when `l == nil'
        break unless l
    end
end
0 голосов
/ 16 декабря 2011

Чтобы подсчитать, сколько раз в тексте встречается одно слово:

text = "word aaa word word word bbb ccc ccc"
text.scan(/\w+/).count("word") # => 4

Для подсчета набора слов:

text = "word aaa word word word bbb ccc ccc"
wlist = text.scan(/\w+/)
wset = ["word", "ccc"]
result = {}
wset.each {|word| result[word] = wlist.count(word) }
result # => {"word" => 4, "ccc" => 2}
result["ccc"] # => 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...