Избегание / удаление nil при использовании оператора case при разборе строки - PullRequest
2 голосов
/ 18 февраля 2010

пример данных:

DNA : 
This is a string

BaseQuality :
4 4 4 4 4 4 6 7 7 7 

Metadata : 
Is_read

DNA : 
yet another string

BaseQuality : 
4 4 4 4 7 7 4 8 4 4 4 4 4

Metadata :
Is_read
SCF_File 
.
.
.

У меня есть метод, который использует оператор case следующим образом для разделения частей более длинного текстового файла на записи, используя разделитель "\ n \ n". И класс, который моделирует объект данных

def parse_file(myfile)
    $/ = "\n\n"
    records = []
    File.open(myfile) do |f|
      f.each_line do |line|
        read = Read.new     
         case line
          when /^DNA/
            read.dna_data = line.strip
          when /^BaseQuality/
            read.quality_data =line.strip
          when /^Metadata/
            read.metadata =line.strip
          else
            puts "Unrecognized line: #{line}"
        end
        records.push read
      end
    end
    records
  end

class Read
attr_accessor :dna_data,:quality_data,:metadata
end

records.each do |r|
 puts r.dna_data
end

данные днк содержат «правильную» строковую часть, а также два нулевых «объекта» / раздражающих ноля!

"This is a string"
nil
nil

Мои проблемы с указанными выше нулевыми строками, которые назначаются для dna_data при использовании read.dna_data = line.

Пожалуйста, как вы избавитесь от них? Как вы избегаете их в первую очередь. Что мне не хватает? Мой подход "вонючий"? Спасибо

Ответы [ 3 ]

2 голосов
/ 18 февраля 2010

Проблема в том, что код создает новый экземпляр Read для каждой строки. Вместо этого он должен создать экземпляр для каждого раздела. Похоже, что раздел начинается с заголовка ДНК, поэтому:

def parse_file(myfile)
  $/ = "\n\n"
  records = []
  File.open(myfile) do |f|
    read = nil                              # <- NEW
    f.each_line do |line|
      #read = Read.new                      # <- DELETED
      case line
      when /^DNA/
        read = Read.new                     # <- NEW
        read.dna_data = line.strip
      when /^BaseQuality/
        read.quality_data = line.strip
      when /^Metadata/
        read.metadata = line.strip
        records.push read                   # <= ADDED
      else
        puts "Unrecognized line: #{line}"
      end
      #records.push read                    # <= DELETED
    end
  end
  records
end

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

def parse_file(myfile)
  $/ = "\n\n"
  records = []
  File.open(myfile) do |f|
    f.each_line do |line|
      read = Read.new
      case line
      when /^DNA/
        records << Read.new
        records.last.dna_data = line.strip
      when /^BaseQuality/
        records.last.quality_data = line.strip
      when /^Metadata/
        records.last.metadata = line.strip
      else
        puts "Unrecognized line: #{line}"
      end
    end
  end
  records
end
2 голосов
/ 19 февраля 2010

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

0 голосов
/ 18 февраля 2010

Во-первых, я бы не использовал Ruby для биоинформатики, он недостаточно быстр для решения определенных проблем. Рано или поздно вы столкнетесь с проблемами, и ваша программа остановится.

Из того, что я собрал, вы пытаетесь удалить nils из массива. Вот два способа сделать это:

  1. используйте компактный метод.

    [ноль, ноль, 'asdfa']. Compact # >> ['asdfa']

  2. не добавлять ноль при добавлении элементов.

    records.push читать, если только не read.nil?

    records.push read, если read # nil оценивается как false.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...