Сравнение двух элементов в разных массивах

#python #arrays #csv #cs50

#python #массивы #csv #cs50

Вопрос:

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

Рассматриваемый фрагмент кода:

 for i in range(row_length):
    print(f"ss_record: {ss_record[i]}")
    print(f"row: {row[i   1]}")
                
    #THIS IF STATEMENT IS NOT WORKING
    if ss_record[i] == row[i   1]:
        count  = 1
    #print()
    #print(f"row length: {row_length}")
    #print(f"count: {count}")
    if count == row_length:
        print(row[0])
        exit(0)
  

Что я сделал: я попытался напечатать значение ss_record и row до того, как оно пройдет через if инструкцию, но когда оно совпадает, count не увеличивается. Я попытался сохранить значение row в новом массиве, но он выдает ошибку и сохраняет только длину массива и первые 2 значения строки и повторяет эти значения в каждом следующем экземпляре.

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

Весь Код целиком:

 import csv
import sys
import re
from cs50 import get_string
from sys import argv

def main():
    line_count = 0
    if len(argv) != 3:
        print("missing command-line argument")
        exit(1)
    
    with open(sys.argv[1], 'r') as database:
        sequence = open(sys.argv[2], 'r')
        string = sequence.read()
        reader = csv.reader(database, delimiter = ',')

        for row in reader:
            if line_count == 0:
                row_length = len(row) - 1
                ss_record = [row_length]
                for i in range(row_length):
                    ss_record.append(ss_count(string, row[i   1], len(row[i   1])))
        
                ss_record.pop(0)
                line_count = 1
            
            else:
                count = 0
                for i in range(row_length):
                    print(f"ss_record: {ss_record[i]}")
                    print(f"row: {row[i   1]}")
                    
                    #THIS IF STATEMENT IS NOT WORKING
                    if ss_record[i] == row[i   1]:
                        count  = 1
                if count == row_length:
                    print(row[0])
                    exit(0)
  
 
#ss_count mean the # of times the substring appear in the string
def ss_count(string, substring, length):
    count = 1
    record = 0
    pos_array = []

    for m in re.finditer(substring, string):
        pos_array.append(m.start())
    
    for i in range(len(pos_array) - 1):
        if pos_array[i   1] - pos_array[i] == length:
                count  = 1
        else:
            if count > record:   
                record = count
            count = 1
    
    if count > record:   
        record = count
    
    return record
main()
  

Значения, используемые для воспроизведения проблемы:

последовательность (это текстовый файл) = AAGGTAAGTTTAGAATATAAAAGGTGAGTTAAATAGAATAGGTTAAAATTAAAGGAGATCAGATCAGATCAGATCTATCTATCTATCTATCTATCAGAAAAGAGTAAATAGTTAAAGAGTAAGATATTGAATTAATGGAAAATATTGTTGGGGAAAGGAGGGATAGAAGG

подстрока (это файл CSV) =
имя, AGATC, AATG, TATC
Алиса, 2,8,3
Боб, 4,1,5
Чарли, 3,2,5

Суть файла CSV: Цифры рядом с Алисой означают, сколько раз подстрока (STR / короткий тандемный повтор) появляется в строке в строке (последовательности ДНК). В этой строке AGATC появляется 4 раза подряд, AATG появляется 1 раз подряд, а TATC появляется 5 раз подряд. Для этой последовательности ДНК она соответствует Bob, и он выводится в качестве ответа.

Ответ №1:

Вы были правы, при сравнении ss_record[i] == row[i 1]: возникает проблема с типом, номера ss_record являются целыми числами, а номера строки — строками. Вы можете подтвердить проблему, напечатав оба ss_record и row :

 print("ss_record: {}".format(ss_record)) -> ss_record: [4, 1, 5]
print("row: {}".format(row)) -> row: ['Alice', '2', '8', '3']
  

Для того, чтобы фрагмент работал, вам просто нужно изменить сравнение на

 ss_record[i] == int(row[i   1])
  

Тем не менее, я чувствую, что код довольно сложный для этой задачи. Класс string реализует count метод, который возвращает количество неперекрывающихся вхождений данной подстроки. Кроме того, поскольку код, с которым он работает, основан на элементах и сильно зависит от манипуляций с индексом, логику итерации сложно отслеживать (IMO). Вот мой подход к проблеме:

 import csv

def match_user(dna_file, user_csv):
    with open(dna_file, 'r') as r:
        dna_seq = r.readline()

    with open(user_csv, 'r') as r:
        reader = csv.reader(r)
        rows = list(reader)

    target_substrings = rows[0][1:]
    users = rows[1:]

    num_matches = [dna_seq.count(target) for target in target_substrings]
    for user in users:
        user_matches = [int(x) for x in user[1:]]
        if user_matches == num_matches:
            return user[0]

    return "Not found"
  

Счастливого кодирования!

Комментарии:

1. Я не понимаю, как работает эта логика: [dna_seq.count(target) for target in target_substrings] . Я понимаю, что это pythonic, но как это работает.

2. @manav-dubey Этот синтаксис называется пониманием списка . По сути, это способ смешивания итерации и вычисления, слегка напоминающий математическую нотацию для построения множеств . Перевод на английский был бы: For every STR check in the dna sequence how many times it appears and save these results into a list