Как преобразовать строку в dict

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

out = str.split() 

И подсчитайте, сколько значений создано:

 print len(out) # Says 192 

Затем я пытаюсь удалить все из списка:

 for x in out: out.remove(x) 

И затем пересчитайте:

 print len(out) # Says 96 

Может кто-нибудь объяснить, почему он говорит 96 вместо 0 ???

БОЛЬШЕ ИНФОРМАЦИИ

Моя строка выглядит так: # one cat #two dogs # three birds В строке нет дубликатов, все слова уникальны.

Итак, что я делаю:

 for x in out: if '#' in x: ind = out.index(x) # Get current index nextValue = out[ind+1] # Get next value myDictionary[x] = nextValue out.remove(nextValue) out.remove(x) 

Проблема в том, что я не могу переместить все пары значений в словарь, поскольку я только перебираю 96 элементов.

Всем спасибо!

8 Solutions collect form web for “Как преобразовать строку в dict”

Я думаю, вы действительно хотите что-то вроде этого:

 s = '#one cat #two dogs #three birds' out = s.split() entries = dict([(x, y) for x, y in zip(out[::2], out[1::2])]) 

Что делает этот код? Давайте сломаем его. Во-первых, мы разделили пробелы так out как вы.

Затем мы перебираем пары, вызывая их « x, y ». Эти пары становятся list кортежей / пар. dict() принимает список двух кортежей размера и обрабатывает их как key, val .

Вот что я получаю, когда пробовал:

 $ cat tryme.py s = '#one cat #two dogs #three birds' out = s.split() entries = dict([(x, y) for x, y in zip(out[::2], out[1::2])]) from pprint import pprint pprint(entries) $ python tryme.py {'#one': 'cat', '#three': 'birds', '#two': 'dogs'} 

Что касается того, что на самом деле произошло в цикле for :

Из документации для оператора Python :

Список выражений оценивается один раз ; он должен давать итерируемый объект. Итератор создается для результата expression_list . Затем пакет выполняется один раз для каждого элемента, предоставленного итератором, в порядке возрастания индексов . Каждый элемент в свою очередь присваивается целевому списку, используя стандартные правила для назначений, а затем выполняется пакет. Когда элементы исчерпаны (что происходит сразу, когда последовательность пуста ), пакет в предложении else , если он присутствует, выполняется, и loop завершается .

Я думаю, что это лучше всего показать с помощью иллюстрации .

Теперь предположим, что у вас есть iterable object (например, list ), например:

 out = [a, b, c, d, e, f] 

Что происходит, когда вы делаете for x in out это то, что он создает внутренний индекс, который выглядит следующим образом (я иллюстрирую его символом ^ ):

 [a, b, c, d, e, f] ^ <-- here is the indexer 

Что обычно происходит, так это то, что: когда вы заканчиваете один цикл цикла, индексщик движется вперед следующим образом:

 [a, b, c, d, e, f] #cycle 1 ^ <-- here is the indexer [a, b, c, d, e, f] #cycle 2 ^ <-- here is the indexer [a, b, c, d, e, f] #cycle 3 ^ <-- here is the indexer [a, b, c, d, e, f] #cycle 4 ^ <-- here is the indexer [a, b, c, d, e, f] #cycle 5 ^ <-- here is the indexer [a, b, c, d, e, f] #cycle 6 ^ <-- here is the indexer #finish, no element is found anymore! 

Как вы можете видеть, индексатор продолжает двигаться вперед до конца вашего списка, независимо от того, что произошло с этим списком !

Таким образом, когда вы remove , это происходит внутри:

 [a, b, c, d, e, f] #cycle 1 ^ <-- here is the indexer [b, c, d, e, f] #cycle 1 - a is removed! ^ <-- here is the indexer [b, c, d, e, f] #cycle 2 ^ <-- here is the indexer [c, d, e, f] #cycle 2 - c is removed ^ <-- here is the indexer [c, d, e, f] #cycle 3 ^ <-- here is the indexer [c, d, f] #cycle 3 - e is removed ^ <-- here is the indexer #the for loop ends 

Обратите внимание, что вместо 6 циклов (!!) существует только 3 цикла (это число элементов в исходном списке). И именно поэтому вы ушли с половиной len вашей оригинальной len , потому что это количество циклов, необходимых для завершения цикла, когда вы удаляете из него один элемент для каждого цикла.


Если вы хотите очистить список, просто выполните:

 if (out != []): out.clear() 

Или, альтернативно, чтобы удалить элемент один за другим, вам нужно сделать это наоборот – от конца до начала . Использовать reversed :

 for x in reversed(out): out.remove(x) 

Теперь, почему бы reversed работа? Если индексатор продолжает двигаться вперед, не будет reversed и не должен работать, потому что количество элементов уменьшается на один за такт в любом случае?

Нет, это не так,

Поскольку reversed метод меняет способ работы внутреннего индексатора! То, что произошло, когда вы используете reversed метод, состоит в том, чтобы заставить внутренний индексщик двигаться назад (от конца), а не вперед .

Чтобы проиллюстрировать это, это обычно происходит:

 [a, b, c, d, e, f] #cycle 1 ^ <-- here is the indexer [a, b, c, d, e, f] #cycle 2 ^ <-- here is the indexer [a, b, c, d, e, f] #cycle 3 ^ <-- here is the indexer [a, b, c, d, e, f] #cycle 4 ^ <-- here is the indexer [a, b, c, d, e, f] #cycle 5 ^ <-- here is the indexer [a, b, c, d, e, f] #cycle 6 ^ <-- here is the indexer #finish, no element is found anymore! 

И, таким образом, когда вы делаете одно удаление за цикл, это не влияет на работу индексатора:

 [a, b, c, d, e, f] #cycle 1 ^ <-- here is the indexer [a, b, c, d, e] #cycle 1 - f is removed ^ <-- here is the indexer [a, b, c, d, e] #cycle 2 ^ <-- here is the indexer [a, b, c, d] #cycle 2 - e is removed ^ <-- here is the indexer [a, b, c, d] #cycle 3 ^ <-- here is the indexer [a, b, c] #cycle 3 - d is removed ^ <-- here is the indexer [a, b, c] #cycle 4 ^ <-- here is the indexer [a, b] #cycle 4 - c is removed ^ <-- here is the indexer [a, b] #cycle 5 ^ <-- here is the indexer [a] #cycle 5 - b is removed ^ <-- here is the indexer [a] #cycle 6 ^ <-- here is the indexer [] #cycle 6 - a is removed ^ <-- here is the indexer 

Надеемся, что иллюстрация поможет вам понять, что происходит внутри …

Вы не конкретны. Почему вы пытаетесь удалить все в списке? Любой, если все, что вам нужно сделать, это очистить список, почему бы просто не сделать это:

 out = [] 

Я считаю, что ты хочешь следовать.

 >>> a = '#one cat #two dogs #three birds' >>> b = { x.strip().split(' ')[0] : x.strip().split(' ')[-1] for x in a.strip().split('#') if len(x) > 0 } >>> b {'three': 'birds', 'two': 'dogs', 'one': 'cat'} 

Или даже лучше

 >>> b = [ y for x in a.strip().split('#') for y in x.strip().split(' ') if len(x) > 0 ] >>> c = { x: y for x,y in zip(b[0::2],b[1::2]) } >>> c {'three': 'birds', 'two': 'dogs', 'one': 'cat'} >>> 

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

Простейшее прямое решение вашей проблемы состоит в том, чтобы перебирать копию , используя нотацию среза:

 for x in out[:]: # ... out.remove(x) 

Однако здесь есть более глубокий вопрос: зачем вам вообще удалять элементы из списка? С вашим алгоритмом вы, как гарантируется, получите пустой список, который вам не нужен. Было бы проще и эффективнее просто перебирать список без удаления элементов.

Когда вы закончите со списком (после блока for-loop), вы можете явно удалить его (используя ключевое слово del ) или просто оставить его для системы сбора мусора Python.

Остается еще одна проблема: вы объединяете прямую итерацию по списку с индексами. Использование for x in out обычно должно быть ограничено ситуациями, когда вы хотите получить доступ к каждому элементу независимо от других. Если вы хотите работать с индексами, используйте for i in range(len(out)) и элементы доступа out[i] .

Кроме того, вы можете использовать понимание словаря для выполнения всей своей задачи в однострочном питоническом выражении:

 my_dictionary = {out[i]: out[i + 1] for i in range(len(out)) if "#" in out[i]} 

Другой альтернативой pythonic было бы использовать тот факт, что каждый элемент с четным номером является ключом, и каждый элемент с нечетным номером является значением (вам нужно было бы предположить, что результат списка str.split() последовательно следует за этим шаблон) и использовать zip для четного и нечетного подписок.

 my_dictionary = dict(zip(out[::2], out[1::2])) 

Если вам просто нужно очистить список,

использовать out = [] или out.clear()

Во всяком случае, вы сказали, что remove функции списка влияет на список.

 out = ['a', 'b', 'c', 'd', 'e', 'f'] for x in out: out.remove(x) print(x) 

то результат показан ниже:

a c e

Это ровно половина полного списка. Итак, в вашем случае у вас есть 96 (половина 192) из ​​192.

Проблема заключается в том, что всякий раз, когда вы удаляете значение из списка, этот список восстанавливает свои значения динамически. То есть, когда вы выполняете out.remove(ind) и out.remove(ind+1) , значения в этих индексах удаляются, но они заменяются новыми значениями, которые являются предшественниками предыдущего значения.

Поэтому, чтобы избежать этого, вы должны реализовать код следующим образом:

 out = [] out = '#one cat #two dogs #three birds'.split() print "The list is : {0} \n".format(out) myDictionary = dict() for x in out: if '#' in x: ind = out.index(x) # Get current index nextValue = out[ind+1] # Get next value myDictionary[x] = nextValue out = [] # #emptying the list print("The dictionary is : {0} \n".format(myDictionary)) 

Итак, после того, как вы закончите перенос значений из списка в словарь, мы можем спокойно удалить его out используя out = []

Проблема в том, что вы используете remove (x) во время итерации. переменная 'out' ссылается как на функцию remove, так и for-loop.

Просто используйте

 for i in range(len(out)): out.remove(out[i]); 
Python - лучший язык программирования в мире.