2016-05-05 6 views
1

Ich versuche, eine Reihe von Klassenobjekten machen zu machen, aber mein Code funktioniert nicht. Wenn ich einen Solution.new machen wird nil zurückgegeben, und ich möchte es in jeder Zeile von test.txt ein Array von Arrays von Wörtern zurückgibt. Ich bin mit Ruby 2.1.5Wie ein Array von Klassenobjekten in Ruby

class Line 
    def initialize (content) 
    @content = content 
    self.line_arr 
    end 
    def line_arr 
    @content.split 
    end 
end 

class Solution 
    def read_file 
    array = [] 
    File.foreach('test.txt') do |line| 
     array << Line.new(line) 
    end 
    end 
end 

Und jetzt, wenn ich eine machen

foo = Solution.new 
foo.read_file 

es nil zurückgibt.

+0

Ruby gibt immer eines von zwei Dingen aus den Methoden zurück: Was Sie ihm mit dem Schlüsselwort 'return' sagen, oder wenn es den Wert des letzten Ausdrucks in der Methode erreicht. –

+0

Auch Ihr Titel ist völlig anders als Ihre Frage. Ihre Frage ist eher wie "Warum gibt diese Methode null statt eines Arrays zurück?" –

Antwort

0
class Line 
    attr_reader :content 

    def initialize (content) 
    @content = content.split(' ') 
    end 
end 

class Solution 
    def read_file 
    array = [] 

    File.foreach('test.txt') do |line| 
     array << Line.new(line).content 
    end 

    array 
    end 
end 

Sie müssen diese Zeile 'array' hinzufügen, da Sie sie vom Methodenaufruf zurückgeben müssen. Auch hier habe ich die Line-Klasse etwas vereinfacht. Grundsätzlich kann dieser Code Ihr Problem lösen, Sie sollten jedoch den regulären Ausdruck zum Analysieren von Zeilen verwenden.

+0

Obwohl dieser Code die Frage beantworten kann, zusätzliche Kontext in Bezug auf _why_ und/oder _how_ es Antworten die Frage würde erheblich verbessern seine langfristige Wert. Bitte [bearbeiten] Sie Ihre Antwort, um eine Erklärung hinzuzufügen. –

0

Try this:

class Line 
    def initialize (content) 
    @content = content 
    self.line_arr 
    end 
    def line_arr 
    @content.split 
    end 
end 

class Solution 

    def initialize 
    self.read_file 
    end 

    def read_file 
    array = [] 
    File.foreach('test.txt') do |line| 
     array << Line.new(line) 
    end 
    array 
    end 
end 
3

Ich glaube nicht, Solution.newnil in Ihrem Beispiel zurückkehrt, wird es eine neue Instanz der Lösung zurückkehrt (foo in Ihrem Beispiel)

Ihr Hauptproblem ist, dass read_file gibt den Wert File.foreach zurück, der immer nil ist.

Für den Anfang, aktualisieren Sie Ihre read_file Methode das Array zurück selbst:

class Solution 
    def read_file 
    array = [] 
    lines = [] 

    File.foreach('test.txt') do |line| 
     lines << Line.new(line) 
    end 

    array << lines 

    array 
    end 
end 

solution = Solution.new 
solution.read_file 
# outputs: 
# [#<Line:0x007fab92163b50 @content="This Is A Line\n">, #<Line:0x007fab92161be8 @content="Line 2\n">, #<Line:0x007fab92160d88 @content="Line3">] 

Wenn Sie ein Array von Arrays zurückgeben möchten jede Zeile Leerzeichen aufgeteilt:

class Solution 
    def read_file 
    lines = [] 
    File.foreach('test.txt') do |line| 
     words = [] 
     line.strip.split(/\s+/).each do |word| 
     words << word 
     end 

     lines << Line.new(words) 
    end 

    lines 
    end 
end 

Der Schlüssel Linie Code ist hier: line.strip.split(/\s+/) die ersten Streifen führenden und leerzeichen aus dem String nachlauf, dann auf ein Array wandelt durch die Zeichenfolge basierend auf Aufspalten leerzeichen (die /s+/ regulären Ausdruck übereinstimmt einem oder mehreren leerzeichen s).

Einige andere Vorschläge:

Geben Sie den Dateinamen als Argument an read_file Sie eine Standard-Argument festlegen können, wenn Sie wollen:

class Solution 
    def read_file(filename = 'test.txt') 
    array = [] 
    File.foreach(filename) do |line| 
     array << Line.new(line) 
    end 

    array 
    end 
end 

schließlich für eine viel elegantere Lösung, Sie kann map verwenden und einfach .split aufrufen, um ein verschachteltes Array zurückzugeben. Die Klasse Line tut in diesem Fall nicht wirklich viel.

Dies wird einfach ein Array von Arrays zurückgeben, wobei das innere Array die Wörter für jede Zeile enthält.

0

Betrachten Enumerable#inject statt der Schaffung unnötiger Variablen zu verwenden:

class Solution 
    def read_file 
    File.foreach('test.txt').inject([]) do |memo, line| 
     memo << Line.new(line) 
    end 
    end 
end 

oder, in diesem speziellen Fall tun map den Trick:

class Solution 
    def read_file 
    File.foreach('test.txt').map &Line.method(:new) 
    end 
end 
0

Wenn alles, was Sie tun müssen, ist erhalten Arrays von Wörtern, und es macht Ihnen nichts aus, die gesamte Datei auf einmal in den Speicher zu laden, dann kann es sehr einfach mit dem folgenden Code getan werden (die 3 Zeilen beginnen mit word_arrays = ..., der Rest ist Setup und Ausgabe):

#!/usr/bin/env ruby 

File.write('woods.txt', 
"The woods are lovely, dark, and deep 
But I have promises to keep 
And miles to go before I sleep 
And miles to go before I sleep") 

word_arrays = File.readlines('woods.txt').each_with_object([]) do |line, word_arrays| 
    word_arrays << line.split 
end 

word_arrays.each.with_index do |words, index| 
    puts "#{index}: #{words} " 
end 

=begin 
Prints: 

0: ["The", "woods", "are", "lovely,", "dark,", "and", "deep"] 
1: ["But", "I", "have", "promises", "to", "keep"] 
2: ["And", "miles", "to", "go", "before", "I", "sleep"] 
3: ["And", "miles", "to", "go", "before", "I", "sleep"] 
=end 
Verwandte Themen