Как добавить элементы в многомерные массивы с расширяющимися значениями - PullRequest
0 голосов
/ 24 мая 2018

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

Например, мой список содержит 4 строки (постоянные) и определенное количество столбцов, основанных на пользовательских записях.Я включаю всю программу только для справки на случай, если возникнут вопросы о том, как все это выглядит:

spacing = '- ' * 45  # formatting for DONOR header
data_list = [['NAMES', 'DONATION AMOUNT', 'Number of Gifts', 'Avg Gifts'],
         ['Rudolph S', 1500, 3, 0],  
         ['Josef M', 250, 5, 0],
         ['Joye A', 5000, 2, None],
         ['Joni M', 2750, 1, None],
         ['Rachelle L', 750, 3, None],
         ['Vena U', 1000, 7, None],
         ['Efrain L', 10000, 1, None],
         ['Mee H', 15000, 2, None],
         ['Tanya E', 50000, 1, None],
         ['Garrett H', 800, 2, None]] 

def addtolist():
"""Method for sending 'Thank You' messages to Donors, using names *"""

    while True:
        print("Enter the name of the person you are writing to (or enter 'list' to see a list of names or Q to quit) ")
        fname_prompt = input("First Name: ").strip().capitalize()
        if fname_prompt.upper() == "Q":
            break
        elif fname_prompt.lower() == "list":  
            if len(data_list) - 1 % 2 != 0:
                for i in range(0, int(len(data_list) - 1 / 2)):
                    cut_off = int((len(data_list)) / 2)
                    if i == 0:               
                        print(spacing)
                        print('{:>44s}'.format(str(data_list[i][0])))  
                        print(spacing)
                    elif cut_off + i >= len(data_list):
                        continue
                    else:
                        print('{:>30s}'.format(data_list[i][0]), '{:>35s}'.format(data_list[cut_off + i][0]))
            else:
                if i == 0:                                                  
                    print(spacing)
                    print('{:>20s}'.format(str(data_list[i])))              
                    print(spacing)
                else:
                    print('{:>15s}'.format(data_list[i][0]), '{:>30s}'.format(data_list[cut_off + i][0]))
        else:
            lname_prompt = input("Last Name: ").strip().capitalize()
            if lname_prompt.upper() == "Q":
                break
            elif lname_prompt.lower() == "list":
                if len(data_list) - 1 % 2 != 0:
                    for i in range(0, int(len(data_list) - 1 / 2)):
                        cut_off = int((len(data_list)) / 2)
                        if i == 0:                                          
                            print(spacing)
                            print('{:>44s}'.format(str(data_list[i][0])))  
                            print(spacing)
                        elif cut_off + i >= len(data_list):
                            continue
                        else:
                            print('{:>30s}'.format(data_list[i][0]), '{:>35s}'.format(data_list[cut_off + i][0]))
                else:
                    if i == 0:  # for each item in list / 2 (5 x)
                        print(spacing)
                        print('{:>20s}'.format(str(data_list[i][0])))  
                        print(spacing)
                    else:
                        print('{:>15s}'.format(data_list[i][0]), '{:>30s}'.format(data_list[cut_off + i][0]))
            else:
                full_name = fname_prompt + " " + lname_prompt
                if full_name != "List List" or full_name != "list ":
                    name_found = False
                    for vals in data_list:
                        if full_name in vals:
                            name_found = True
                        else:
                            name_found = False

                        if name_found is False:
                            add_name = input("That name is not in the Donor list. Do you want to add it to the list?  ").upper()
                            if add_name == "Y":                                         
                                data_list.append([full_name])
                                if len(data_list) - 1 % 2 != 0:
                                    for i in range(0, int(len(data_list) - (len(data_list) - 2) / 2)):
                                        cut_off = int((len(data_list)) / 2)
                                            if i == 0:                                          
                                                print(spacing)
                                                print('{:>44s}'.format(str(data_list[i][0])))
                                                print(spacing)
                                            elif cut_off + i >= len(data_list):
                                                 print('{:>30s}'.format(data_list[i][0]))
                                                continue
                                            else:
                                                print('{:>30s}'.format(data_list[i][0]), '{:>35s}'.format(data_list[cut_off + i][0]))
                                 else:
                                     if i == 0:  # for each item in list / 2 (5 x)
                                         print(spacing)
                                         print('{:>20s}'.format(str(data_list[i][0])))  
                                         print(spacing)
                                     else:
                                         print('{:>15s}'.format(data_list[i][0]), '{:>30s}'.format(data_list[cut_off + i][0]))

                             donation_amt = int(input("Enter in the donation amount from Donor {0}: $".format(full_name)))
                             print('{0} has donated ${1}'.format(full_name, donation_amt))
                             data_list.append(donation_amt) # difficulty HERE
                             print(data_list)

Основные строки, с которыми у меня возникли сложности, находятся в самом конце с комментарием "Сложно ЗДЕСЬ ".

data_list.append(donation_amt) # difficulty HERE

Я пытаюсь сделать так, чтобы, когда пользователь вводит новое имя и новую сумму пожертвования (или если он просто выбирает существующее имя и прикрепляет к нему сумму пожертвования), программа моглалибо добавьте / вставьте денежное значение в связанный подсписок (имя, к которому он прикреплен).как я его сейчас настроил, он просто добавляет числовую сумму в конец большего списка, но мне не удалось прикрепить значение к подсписку ... Кто-нибудь делал что-то подобное раньше?

Ответы [ 4 ]

0 голосов
/ 24 мая 2018

Двумерные списки в Python - это просто списки списков.Таким образом, каждый элемент data_list сам по себе является списком.Вот пример доступа к элементу, первому элементу ниже вашей строки заголовков (таким образом, индекс 1):

>>> first_entry = data_list[1]
>>> first_entry
['Rudolph S', 1500, 3, 0]

Начиная с data_list[1] (который мы сохранили как переменную с именем first_entry)это также список, к которому мы можем получить доступ, мы можем получить доступ к четвертому элементу (по индексу 3, поскольку списки начинают индексироваться с 0) первой записи следующим образом:

>>> first_entry = data_list[1]
>>> fourth_element = first_entry[3]
>>> fourth_element
0

Или, более кратко:

>>> data_list[1][3]
0

Итак, чтобы начать отвечать на ваш вопрос, если вашей целью было обновить сумму пожертвования "Joye A", вы должны использовать data_list[3][1] = donation_amt.Это потому, что запись Джой находится в индексе 3 основного списка, а пожертвования записаны в индексе 1 ее подсписка.

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

Использование вашей матрицы

Сначала вам нужно будет определить, является ли имяуже существует.В результате было бы лучше создать дополнительный список, который содержит только первый столбец, 1-й список.Вы можете сделать это любым количеством способов.Я покажу это как понимание списка:

>>> names_only = [e[0] for e in data_list]
>>> names_only
['NAMES', 'Rudolph S', 'Josef M', ...]

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

Сначала вы проверяете, существует ли имя в матрице:

>>> 'Josef M' in names_only
True

Если это так, теперь вам нужно найти индекс искомого имени.Списки в Python имеют функцию индекса:

>>> idx = names_only.index('Joesf M')
>>> idx
2

Теперь вы обновляете его сумму пожертвования, как описано выше:

>>> data_list[idx][1] = donation_amt

Теперь, если его нет в матрице, мы хотимсделать совершенно новый ряд.Давайте представим, что мы обрабатываем пользователя с именем 'bob'.Он еще не в матрице.Здесь вы используете функцию добавления:

>>> data_list.append([bob, donation_amt, 1, None])

Где 1 и None могут быть заменены значениями по умолчанию.Собираем все вместе как функцию:

>>> def update_or_create(name, amt):
...   names = [e[0] for e in data_list]
...   if name in names:
...      idx = names.index(name)
...      data_list[idx][1] = amt
...   else:
...      data_list.append([name, amt, 1, None])

Должен делать то, что вы просите.

Наконец

Было бы лучше использовать другую структуру для этого.Я бы предложил структуру dict вроде:

new_structure = {NAME: {'donation': DONATION_AMT, 'num_gifts': NUM_GIFTS, 'avg_amt': AVERAGE_DONATION},...}

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

>>> def update_or_create(name, amt):
...   if name in new_structure:
...       new_structure[name]['donation'] = amt
...   else:
...       new_structure.update({name: {'donation': amt, 'num_gifts': 1, 'avg_amt': None}})

Намного приятнее.

0 голосов
/ 24 мая 2018

Кажется, у вас есть 4 статических столбца и неопределенное количество строк.

Рассматривали ли вы использование списка словарей, что-то вроде json doc?

    data_list = [{
            'NAME':'Rudolph S',
            'DONATION AMOUNT' : 1500,
            'Number of Gifts' : 3,
            'Avg Gifts' :  0
        },{
            'NAME':'Josef M',
            'DONATION AMOUNT' : 250,
            'Number of Gifts' : 5,
            'Avg Gifts' :  None
        }]

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

0 голосов
/ 24 мая 2018

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

data_list.append(donation_amt) # difficulty HERE

на:

# Determine index where the donor belongs
idx = -1
for item in range(0, len(data_list)):
    if data_list[item][0] == full_name:
        idx = item
        break

# Append to the sublist
data_list[idx].append(donation_amt)

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

0 голосов
/ 24 мая 2018

Трехмерные списки имеют возможность добавления в основной список или в один из подсписков.

data_list.append(donation_amt)

добавится в основной список, что будет означать, что если бы у вас был списоккак и ваш, это добавит в конец.

[['NAMES', 'DONATION AMOUNT', 'Number of Gifts', 'Avg Gifts'],
     ['Rudolph S', 1500, 3, 0],  
     ['Josef M', 250, 5, 0],
     ['Joye A', 5000, 2, None],
     ['Joni M', 2750, 1, None],
     ['Rachelle L', 750, 3, None],
     ['Vena U', 1000, 7, None],
     ['Efrain L', 10000, 1, None],
     ['Mee H', 15000, 2, None],
     ['Tanya E', 50000, 1, None],
     ['Garrett H', 800, 2, None],
      [donation_amt]]

Если вы хотите добавить сумму пожертвования к определенному индексу, используйте

data_list[index].append(donation_amt).

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

...