私はプログラミングの初心者なので、CS50コースを受講することにしました。 Problem Set6(Python)でコードを書いたところ、小さなデータベースでは機能しましたが、大きなデータベースでは失敗しました。こちらが コースページ です。 こちらからダウンロード (Googleドライブから)
マイコード
_import csv
from sys import argv
class DnaTest(object):
"""CLASS HELP: the DNA test, simply give DNA sequence to the program, and it searches in the database to
determine the person who owns the sample.
type the following in cmd to run the program:
python dna.py databases/small.csv sequences/1.txt """
def __init__(self):
# get filename from the command line without directory names "database" and "sequence"
self.sequence_argv = str(argv[2][10:])
self.database_argv = str(argv[1][10:])
# Automatically open and close the database file
with open(f"databases/{self.database_argv}", 'r') as database_file:
self.database_file = database_file.readlines()
# Automatically open and close the sequence file
with open(f"sequences/{self.sequence_argv}", 'r') as sequence_file:
self.sequence_file = sequence_file.readline()
# Read CSV file as a dictionary, function: compare_database_with_sequence()
self.csv_database_dictionary = csv.DictReader(self.database_file)
# Read CSV file to take the first row, function: get_str_list()
self.reader = csv.reader(self.database_file)
# computed dictionary from the sequence file
self.dict_from_sequence = {}
# returns the first row of the CSV file (database file)
def get_str_list(self):
# get first row from CSV file
self.keys = next(self.reader)
# remove 'name' from list, get STR only.
self.keys.remove("name")
return self.keys
# returns dictionary of computed STRs from the sequence file (key(STR): value(count))
def get_str_count_from_sequence(self): # PROBLEM HERE AND RETURN DICTIONARY FROM IT !
for dna_seq in self.get_str_list():
self.dict_from_sequence.update({dna_seq: self.sequence_file.count(dna_seq)})
# compare computed dictionary with the database dictionaries and get the person name
def compare_database_with_sequence(self):
for dictionary in self.csv_database_dictionary:
dict_from_database = dict(dictionary)
dict_from_database.pop('name')
# compare the database dictionaries with sequence computed dictionary
shared_items = {k: self.dict_from_sequence[k] for k in self.dict_from_sequence if
k in dict_from_database and self.dict_from_sequence[k] == int(dict_from_database[k])}
if len(self.dict_from_sequence) == len(shared_items):
dict_from_database = dict(dictionary)
print(dict_from_database['name'])
break
# run the class and its functions (Program control)
if __name__ == '__main__':
RunTest = DnaTest()
RunTest.get_str_count_from_sequence()
RunTest.compare_database_with_sequence()
_
問題は
関数get_str_count_from_sequence(self):
でcountを使用します。これは機能しますが、Sequentialシーケンスの場合、シーケンスファイル(例5.txt)では、必要なシーケンスは非シーケンシャルであり、連続するシーケンスの数をすべて比較することはできません。探しましたが、簡単なことは何も見つかりませんでした。 Regexモジュールを使用するものとreモジュールを使用するものがありますが、解決策は見つかりませんでした。
テストコード:
CS50サイトから:プログラムをpython _dna.py databases/large.csv sequences/6.txt
_として実行します。プログラムはLuna
を出力するはずです
仕様
「Piyush Singh」に感謝します。私はあなたのアドバイスに取り組み、re
を使用して問題を解決しました。最初に、re
を使用してグループ(最長の連続シーケンス)を選択し、辞書である一致グループを設定してから、各STRの最大値を取得し、次に辞書データをクリアして次のSTR=を保存し、ここで比較関数の辞書を更新しました(データベースから読み取り、シーケンスファイルから計算しました)。
import csv
from sys import argv
import re
class DnaTest(object):
"""CLASS HELP: the DNA test, simply give DNA sequence to the program, and it searches in the database to
determine the person who owns the sample.
type the following in cmd to run the program:
python dna.py databases/small.csv sequences/1.txt """
def __init__(self):
# get filename from the command line without directory names "database" and "sequence"
self.sequence_argv = str(argv[2][10:])
self.database_argv = str(argv[1][10:])
# Automatically open and close the database file
with open(f"databases/{self.database_argv}", 'r') as database_file:
self.database_file = database_file.readlines()
# Automatically open and close the sequence file
with open(f"sequences/{self.sequence_argv}", 'r') as sequence_file:
self.sequence_file = sequence_file.readline()
# Read CSV file as a dictionary, function: compare_database_with_sequence()
self.csv_database_dictionary = csv.DictReader(self.database_file)
# Read CSV file to take the first row, function: get_str_list()
self.reader = csv.reader(self.database_file)
# computed dictionary from the sequence file
self.dict_from_sequence = {}
self.select_max = {}
# returns the first row of the CSV file (database file)
def get_str_list(self):
# get first row from CSV file
keys = next(self.reader)
# remove 'name' from list, get STR only.
keys.remove("name")
return keys
# returns dictionary of computed STRs from the sequence file (key(STR): value(count))
def get_str_count_from_sequence(self): # PROBLEM HERE AND RETURN DICTIONARY FROM IT !
for str_key in self.get_str_list():
regex = rf"({str_key})+"
matches = re.finditer(regex, self.sequence_file, re.MULTILINE)
# my code
for match in matches:
match_len = len(match.group())
key_len = len(str_key)
self.select_max[match] = match_len
# select max value from results dictionary (select_max)
max_values = max(self.select_max.values())
if max_values >= key_len:
result = int(max_values / key_len)
self.select_max[str_key] = result
self.dict_from_sequence[str_key] = result
# clear compare dictionary to select new key
self.select_max.clear()
# compare computed dictionary with the database dictionaries and get the person name
def compare_database_with_sequence(self):
# comparison function between database dictionary and sequence computed dictionary
def dicts_equal(from_sequence, from_database):
""" return True if all keys and values are the same """
return all(k in from_database and int(from_sequence[k]) == int(from_database[k]) for k in from_sequence) \
and all(k in from_sequence and int(from_sequence[k]) == int(from_database[k]) for k in from_database)
def check_result():
for dictionary in self.csv_database_dictionary:
dict_from_database = dict(dictionary)
dict_from_database.pop('name')
if dicts_equal(self.dict_from_sequence, dict_from_database):
dict_from_database = dict(dictionary)
print(dict_from_database['name'])
return True
if check_result():
pass
else:
print("No match")
# run the class and its functions (Program control)
if __name__ == '__main__':
RunTest = DnaTest()
RunTest.get_str_count_from_sequence()
RunTest.compare_database_with_sequence()
ソリューションを確認
Run your program as python dna.py databases/small.csv sequences/1.txt. Your program should output Bob.
Run your program as python dna.py databases/small.csv sequences/2.txt. Your program should output No match.
さらにチェックするには CS50 DNA 問題セット