如何将字符串空格分隔的键,唯一字的值对转换为字典

use*_*655 9 python iteration split loops list

我有一个字符串,其中的单词用空格分隔(所有单词都是唯一的,没有重复).我将此字符串转换为列表:

s = "#one cat #two dogs #three birds"
out = s.split()
Run Code Online (Sandbox Code Playgroud)

并计算创建的值的数量:

print len(out) # Says 192 
Run Code Online (Sandbox Code Playgroud)

然后我尝试从列表中删除所有内容:

for x in out:
     out.remove(x)
Run Code Online (Sandbox Code Playgroud)

然后重新计算:

print len(out) # Says 96 
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么它说96而不是0?

更多信息

每行以'#'开头,实际上是一对以空格分隔的单词:对中的第一个是键,第二个是值.

所以,我在做的是:

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) 
Run Code Online (Sandbox Code Playgroud)

问题是我不能将所有键,值对移动到字典中,因为我只迭代96个项目.

Ian*_*Ian 13

至于for循环中实际发生的事情:

Python for语句文档:

表达式列表评估一次 ; 它应该产生一个可迭代的对象.为结果创建一个迭代器expression_list.然后,对于迭代器提供的每个项,按升序索引的顺序执行一次该套件.依次使用标准的分配规则将每个项目分配给目标列表,然后执行该套件.当项目耗尽时(序列为时立即),子句中的套件(如果存在)将被执行,并终止.elseloop

我认为最好借助插图来展示.

现在,假设您有这样的iterable object(例如list):

out = [a, b, c, d, e, f]
Run Code Online (Sandbox Code Playgroud)

你做的for x in out是它创建了内部索引器,就像这样(我用符号说明^):

[a, b, c, d, e, f]
 ^  <-- here is the indexer
Run Code Online (Sandbox Code Playgroud)

通常会发生的是:当你完成循环的一个循环时,索引器会向前移动,如下所示:

[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!
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,无论列表中发生了什么,索引器都会一直向前移动到列表的末尾!

因此,当你这样做时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
Run Code Online (Sandbox Code Playgroud)

请注意,那里只有3个循环而不是6个循环(!!)(这是原始列​​表中元素的数量).这就是为什么你留下原来的一半 ,因为这是你在每个循环中从中删除一个元素时完成循环所需的循环次数.lenlen


如果要清除列表,只需执行以下操作:

if (out != []):
    out.clear()
Run Code Online (Sandbox Code Playgroud)

或者,或者,要逐个删除元素,您需要反过来 - 从结束到开始.用途reversed:

for x in reversed(out):
    out.remove(x)
Run Code Online (Sandbox Code Playgroud)

现在,为什么要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!
Run Code Online (Sandbox Code Playgroud)

因此,当您每个周期执行一次删除时,它不会影响索引器的工作方式:

[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
Run Code Online (Sandbox Code Playgroud)

希望插图可以帮助您了解内部发生的事情......


Bri*_*ain 8

我想你其实想要这样的东西:

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

这段代码在做什么?让我们分解吧.首先,我们按照你s的空白划分out.

接下来,我们迭代对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'}
Run Code Online (Sandbox Code Playgroud)