标签归档:dictionary

过滤python词典中的项,其中键包含特定的字符串

问题:过滤python词典中的项,其中键包含特定的字符串

我是用python开发东西的C编码器。我知道如何在C语言中执行以下操作(以及因此在应用于Python的类似C的逻辑中),但是我想知道这样做的“ Python”方式是什么。

我有一个字典d,我想对项的子集进行操作,只有那些键(字符串)的项包含特定的子字符串。

即C逻辑将是:

for key in d:
    if filter_string in key:
        # do something
    else
        # do nothing, continue

我在想python版本会像

filtered_dict = crazy_python_syntax(d, substring)
for key,value in filtered_dict.iteritems():
    # do something

我在这里找到了很多有关过滤字典的文章,但是找不到与之相关的文章。

我的字典未嵌套,我正在使用python 2.7

I’m a C coder developing something in python. I know how to do the following in C (and hence in C-like logic applied to python), but I’m wondering what the ‘Python’ way of doing it is.

I have a dictionary d, and I’d like to operate on a subset of the items, only those who’s key (string) contains a specific substring.

i.e. the C logic would be:

for key in d:
    if filter_string in key:
        # do something
    else
        # do nothing, continue

I’m imagining the python version would be something like

filtered_dict = crazy_python_syntax(d, substring)
for key,value in filtered_dict.iteritems():
    # do something

I’ve found a lot of posts on here regarding filtering dictionaries, but couldn’t find one which involved exactly this.

My dictionary is not nested and i’m using python 2.7


回答 0

字典理解如何:

filtered_dict = {k:v for k,v in d.iteritems() if filter_string in k}

您所看到的它应该是不言自明的,因为它的英语读起来很好。

此语法要求Python 2.7或更高版本。

在Python 3中,只有dict.items()iteritems()所以您可以使用:

filtered_dict = {k:v for (k,v) in d.items() if filter_string in k}

How about a dict comprehension:

filtered_dict = {k:v for k,v in d.iteritems() if filter_string in k}

One you see it, it should be self-explanatory, as it reads like English pretty well.

This syntax requires Python 2.7 or greater.

In Python 3, there is only dict.items(), not iteritems() so you would use:

filtered_dict = {k:v for (k,v) in d.items() if filter_string in k}

回答 1

选择最易读和易于维护的内容。仅仅因为您可以将其写成一行并不意味着您应该这样做。您现有的解决方案与我将要使用的迭代器跳过用户查找值的方法很接近,并且我讨厌如果不能避免,则使用嵌套的ifs:

for key, val in d.iteritems():
    if filter_string not in key:
        continue
    # do something

但是,如果您确实想要让您迭代筛选的dict的东西,那么我将不会执行构建筛选的dict然后对其进行迭代的两步过程,而是使用生成器,因为比pythonic(和超赞的)要好得多生成器?

首先,我们创建我们的生成器,并且良好的设计要求我们使它足够抽象以便可重用:

# The implementation of my generator may look vaguely familiar, no?
def filter_dict(d, filter_string):
    for key, val in d.iteritems():
        if filter_string not in key:
            continue
        yield key, val

然后,我们可以使用生成器通过简单易懂的代码很好地,干净地解决您的问题:

for key, val in filter_dict(d, some_string):
    # do something

简而言之:生成器很棒。

Go for whatever is most readable and easily maintainable. Just because you can write it out in a single line doesn’t mean that you should. Your existing solution is close to what I would use other than I would user iteritems to skip the value lookup, and I hate nested ifs if I can avoid them:

for key, val in d.iteritems():
    if filter_string not in key:
        continue
    # do something

However if you realllly want something to let you iterate through a filtered dict then I would not do the two step process of building the filtered dict and then iterating through it, but instead use a generator, because what is more pythonic (and awesome) than a generator?

First we create our generator, and good design dictates that we make it abstract enough to be reusable:

# The implementation of my generator may look vaguely familiar, no?
def filter_dict(d, filter_string):
    for key, val in d.iteritems():
        if filter_string not in key:
            continue
        yield key, val

And then we can use the generator to solve your problem nice and cleanly with simple, understandable code:

for key, val in filter_dict(d, some_string):
    # do something

In short: generators are awesome.


回答 2

您可以使用内置的过滤器功能根据特定条件过滤字典,列表等。

filtered_dict = dict(filter(lambda item: filter_str in item[0], d.items()))

优点是您可以将其用于不同的数据结构。

You can use the built-in filter function to filter dictionaries, lists, etc. based on specific conditions.

filtered_dict = dict(filter(lambda item: filter_str in item[0], d.items()))

The advantage is that you can use it for different data structures.


回答 3

input = {"A":"a", "B":"b", "C":"c"}
output = {k:v for (k,v) in input.items() if key_satifies_condition(k)}
input = {"A":"a", "B":"b", "C":"c"}
output = {k:v for (k,v) in input.items() if key_satifies_condition(k)}

回答 4

乔纳森(Jonathon)在他的回答中给了你运用字典理解的方法。这是处理您要做的事情的一种方法。

如果您想对字典的值做一些事情,则根本不需要字典理解:

我正在使用iteritems(),因为您用标记了您的问题

results = map(some_function, [(k,v) for k,v in a_dict.iteritems() if 'foo' in k])

现在,结果将出现在列表中,该列表some_function应用于已包含foo在其键中的字典的每个键/值对。

如果只想处理值并忽略键,则只需更改列表理解即可:

results = map(some_function, [v for k,v in a_dict.iteritems() if 'foo' in k])

some_function 可以是任何可调用的,因此lambda也可以工作:

results = map(lambda x: x*2, [v for k,v in a_dict.iteritems() if 'foo' in k])

内部列表实际上不是必需的,因为您还可以传递生成器表达式来映射:

>>> map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))
[4]

Jonathon gave you an approach using dict comprehensions in his answer. Here is an approach that deals with your do something part.

If you want to do something with the values of the dictionary, you don’t need a dictionary comprehension at all:

I’m using iteritems() since you tagged your question with

results = map(some_function, [(k,v) for k,v in a_dict.iteritems() if 'foo' in k])

Now the result will be in a list with some_function applied to each key/value pair of the dictionary, that has foo in its key.

If you just want to deal with the values and ignore the keys, just change the list comprehension:

results = map(some_function, [v for k,v in a_dict.iteritems() if 'foo' in k])

some_function can be any callable, so a lambda would work as well:

results = map(lambda x: x*2, [v for k,v in a_dict.iteritems() if 'foo' in k])

The inner list is actually not required, as you can pass a generator expression to map as well:

>>> map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))
[4]

Python:TypeError:无法散列的类型:“列表”

问题:Python:TypeError:无法散列的类型:“列表”

我正在尝试拍摄一个看起来像这样的文件

AAA x 111
AAB x 111
AAA x 112
AAC x 123
...

并使用字典使输出看起来像这样

{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}

这就是我尝试过的

file = open("filename.txt", "r") 
readline = file.readline().rstrip()
while readline!= "":
    list = []
    list = readline.split(" ")
    j = list.index("x")
    k = list[0:j]
    v = list[j + 1:]
    d = {}
    if k not in d == False:
        d[k] = []
    d[k].append(v)
    readline = file.readline().rstrip()

我不断收到TypeError: unhashable type: 'list'。我知道字典中的键不能是列表,但是我试图将我的值变成列表而不是键。我想知道我是否在某个地方犯了一个错误。

I’m trying to take a file that looks like this:

AAA x 111
AAB x 111
AAA x 112
AAC x 123
...

And use a dictionary to so that the output looks like this

{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}

This is what I’ve tried

file = open("filename.txt", "r") 
readline = file.readline().rstrip()
while readline!= "":
    list = []
    list = readline.split(" ")
    j = list.index("x")
    k = list[0:j]
    v = list[j + 1:]
    d = {}
    if k not in d == False:
        d[k] = []
    d[k].append(v)
    readline = file.readline().rstrip()

I keep getting a TypeError: unhashable type: 'list'. I know that keys in a dictionary can’t be lists but I’m trying to make my value into a list not the key. I’m wondering if I made a mistake somewhere.


回答 0

如其他答案所示,错误是由于造成的k = list[0:j],您的密钥被转换为列表。您可以尝试做的一件事是重新编写代码以利用该split功能:

# Using with ensures that the file is properly closed when you're done
with open('filename.txt', 'rb') as f:
  d = {}
  # Here we use readlines() to split the file into a list where each element is a line
  for line in f.readlines():
    # Now we split the file on `x`, since the part before the x will be
    # the key and the part after the value
    line = line.split('x')
    # Take the line parts and strip out the spaces, assigning them to the variables
    # Once you get a bit more comfortable, this works as well:
    # key, value = [x.strip() for x in line] 
    key = line[0].strip()
    value = line[1].strip()
    # Now we check if the dictionary contains the key; if so, append the new value,
    # and if not, make a new list that contains the current value
    # (For future reference, this is a great place for a defaultdict :)
    if key in d:
      d[key].append(value)
    else:
      d[key] = [value]

print d
# {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}

请注意,如果您使用的是Python 3.x,则必须稍作调整才能使其正常运行。如果您使用打开文件rb,则需要使用line = line.split(b'x')(确保使用正确的字符串类型分割字节)。您也可以使用with open('filename.txt', 'rU') as f:(甚至with open('filename.txt', 'r') as f:)打开文件,它应该可以正常工作。

As indicated by the other answers, the error is to due to k = list[0:j], where your key is converted to a list. One thing you could try is reworking your code to take advantage of the split function:

# Using with ensures that the file is properly closed when you're done
with open('filename.txt', 'rb') as f:
  d = {}
  # Here we use readlines() to split the file into a list where each element is a line
  for line in f.readlines():
    # Now we split the file on `x`, since the part before the x will be
    # the key and the part after the value
    line = line.split('x')
    # Take the line parts and strip out the spaces, assigning them to the variables
    # Once you get a bit more comfortable, this works as well:
    # key, value = [x.strip() for x in line] 
    key = line[0].strip()
    value = line[1].strip()
    # Now we check if the dictionary contains the key; if so, append the new value,
    # and if not, make a new list that contains the current value
    # (For future reference, this is a great place for a defaultdict :)
    if key in d:
      d[key].append(value)
    else:
      d[key] = [value]

print d
# {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}

Note that if you are using Python 3.x, you’ll have to make a minor adjustment to get it work properly. If you open the file with rb, you’ll need to use line = line.split(b'x') (which makes sure you are splitting the byte with the proper type of string). You can also open the file using with open('filename.txt', 'rU') as f: (or even with open('filename.txt', 'r') as f:) and it should work fine.


回答 1

注意: 此答案未明确回答所提问题。其他答案可以做到。由于问题是特定于场景的,提出的异常是一般的,因此此答案指向一般情况。

哈希值只是整数,用于在字典查找期间快速比较字典关键字。

在内部,hash()方法调用__hash__()对象的方法,该方法默认为任何对象设置。

嵌套列表转换为集合

>>> a = [1,2,3,4,[5,6,7],8,9]
>>> set(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

发生这种情况是因为列表内的列表是不能散列的列表。可以通过将内部嵌套列表转换为元组来解决,

>>> set([1, 2, 3, 4, (5, 6, 7), 8, 9])
set([1, 2, 3, 4, 8, 9, (5, 6, 7)])

显式哈希嵌套列表

>>> hash([1, 2, 3, [4, 5,], 6, 7])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'


>>> hash(tuple([1, 2, 3, [4, 5,], 6, 7]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

>>> hash(tuple([1, 2, 3, tuple([4, 5,]), 6, 7]))
-7943504827826258506

避免此错误的解决方案是将列表重组为具有嵌套元组而不是列表。

Note: This answer does not explicitly answer the asked question. the other answers do it. Since the question is specific to a scenario and the raised exception is general, This answer points to the general case.

Hash values are just integers which are used to compare dictionary keys during a dictionary lookup quickly.

Internally, hash() method calls __hash__() method of an object which are set by default for any object.

Converting a nested list to a set

>>> a = [1,2,3,4,[5,6,7],8,9]
>>> set(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

This happens because of the list inside a list which is a list which cannot be hashed. Which can be solved by converting the internal nested lists to a tuple,

>>> set([1, 2, 3, 4, (5, 6, 7), 8, 9])
set([1, 2, 3, 4, 8, 9, (5, 6, 7)])

Explicitly hashing a nested list

>>> hash([1, 2, 3, [4, 5,], 6, 7])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'


>>> hash(tuple([1, 2, 3, [4, 5,], 6, 7]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

>>> hash(tuple([1, 2, 3, tuple([4, 5,]), 6, 7]))
-7943504827826258506

The solution to avoid this error is to restructure the list to have nested tuples instead of lists.


回答 2

您正在尝试使用k(这是一个列表)作为的键d。列表是可变的,不能用作字典键。

另外,由于这一行,您永远不会初始化字典中的列表:

if k not in d == False:

应该是:

if k not in d == True:

实际上应该是:

if k not in d:

You’re trying to use k (which is a list) as a key for d. Lists are mutable and can’t be used as dict keys.

Also, you’re never initializing the lists in the dictionary, because of this line:

if k not in d == False:

Which should be:

if k not in d == True:

Which should actually be:

if k not in d:

回答 3

之所以会出现unhashable type: 'list'异常,是因为k = list[0:j]将其设置k为列表的“切片”,从逻辑上讲,它是另一个(通常较短的)列表。您需要的只是获得列表中的第一项,这样写k = list[0]。对于的调用返回的列表的第三个元素v = list[j + 1:]应该是相同的。v = list[2]readline.split(" ")

我注意到了代码的其他一些可能的问题,我将提及其中的一些问题。一个大的一个是你不希望(重新)初始化dd = {}每一行的循环中读取。另一个是,将变量命名为任何内置类型通常不是一个好主意,因为它会阻止您在需要时访问其中一个变量,并且会使习惯于该变量的其他人感到困惑。指定这些标准项目之一的名称。因此,您应该将变量list变量重命名为其他名称,以避免类似的问题。

这是您的工作版本,其中进行了这些更改,我还简化了if您拥有的语句表达式,该语句表达式可检查键是否已在字典中-甚至有更短的隐式方法来执行此类操作,但使用条件语句声明目前还不错。

d = {}
file = open("filename.txt", "r")
readline = file.readline().rstrip()
while readline:
    lst = readline.split(" ") # Split into sequence like ['AAA', 'x', '111'].
    k = lst[0]  # First item.
    v = lst[2]  # Third item.
    if k not in d:  # New key?
        d[k] = []  # Initialize its associated value to an empty list.
    d[k].append(v)
    readline = file.readline().rstrip()

file.close()  # Done reading file.
print('d: {}'.format(d))

输出:

d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}

The reason you’re getting the unhashable type: 'list' exception is because k = list[0:j] sets k to be a “slice” of the list, which is logically another, often shorter, list. What you need is to get just the first item in list, written like so k = list[0]. The same for v = list[j + 1:] which should just be v = list[2] for the third element of the list returned from the call to readline.split(" ").

I noticed several other likely problems with the code, of which I’ll mention a few. A big one is you don’t want to (re)initialize d with d = {} for each line read in the loop. Another is it’s generally not a good idea to name variables the same as any of the built-ins types because it’ll prevent you from being able to access one of them if you need it — and it’s confusing to others who are used to the names designating one of these standard items. For that reason, you ought to rename your variable list variable something different to avoid issues like that.

Here’s a working version of your with these changes in it, I also replaced the if statement expression you used to check to see if the key was already in the dictionary and now make use of a dictionary’s setdefault() method to accomplish the same thing a little more succinctly.

d = {}
with open("nameerror.txt", "r") as file:
    line = file.readline().rstrip()
    while line:
        lst = line.split() # Split into sequence like ['AAA', 'x', '111'].
        k, _, v = lst[:3]  # Get first and third items.
        d.setdefault(k, []).append(v)
        line = file.readline().rstrip()

print('d: {}'.format(d))

Output:

d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}

回答 4

之所以TypeError会发生,k是因为是一个列表,因为它是使用另一个带有line的列表中的一个切片创建的k = list[0:j]。这可能类似于k = ' '.join(list[0:j]),因此您需要一个字符串。

除此之外,if正如Jesse的回答所指出的那样,您的陈述不正确,应该读为if k not in dif not k in d(我更喜欢后者)。

您还需要d = {}for循环中清除字典,因为每次迭代都在其中。

请注意,您也不应使用listfile作为变量名,因为您将掩盖内建函数。

这是我重写代码的方法:

d = {}
with open("filename.txt", "r") as input_file:
    for line in input_file:
        fields = line.split()
        j = fields.index("x")
        k = " ".join(fields[:j])
        d.setdefault(k, []).append(" ".join(fields[j+1:]))

dict.setdefault()上面的方法替换了if k not in d代码中的逻辑。

The TypeError is happening because k is a list, since it is created using a slice from another list with the line k = list[0:j]. This should probably be something like k = ' '.join(list[0:j]), so you have a string instead.

In addition to this, your if statement is incorrect as noted by Jesse’s answer, which should read if k not in d or if not k in d (I prefer the latter).

You are also clearing your dictionary on each iteration since you have d = {} inside of your for loop.

Note that you should also not be using list or file as variable names, since you will be masking builtins.

Here is how I would rewrite your code:

d = {}
with open("filename.txt", "r") as input_file:
    for line in input_file:
        fields = line.split()
        j = fields.index("x")
        k = " ".join(fields[:j])
        d.setdefault(k, []).append(" ".join(fields[j+1:]))

The dict.setdefault() method above replaces the if k not in d logic from your code.


回答 5

    python 3.2

    with open("d://test.txt") as f:
              k=(((i.split("\n"))[0].rstrip()).split() for i in f.readlines())
              d={}
              for i,_,v in k:
                      d.setdefault(i,[]).append(v)
    python 3.2

    with open("d://test.txt") as f:
              k=(((i.split("\n"))[0].rstrip()).split() for i in f.readlines())
              d={}
              for i,_,v in k:
                      d.setdefault(i,[]).append(v)

python pandas dataframe到字典

问题:python pandas dataframe到字典

我有两列数据框,打算将其转换为python字典-第一列将是键,第二列将是值。先感谢您。

数据框:

    id    value
0    0     10.2
1    1      5.7
2    2      7.4

I’ve a two columns dataframe, and intend to convert it to python dictionary – the first column will be the key and the second will be the value. Thank you in advance.

Dataframe:

    id    value
0    0     10.2
1    1      5.7
2    2      7.4

回答 0

请参阅有关的文档to_dict。您可以像这样使用它:

df.set_index('id').to_dict()

如果只有一列,为避免列名也是dict中的一个级别(实际上,在这种情况下,请使用Series.to_dict()):

df.set_index('id')['value'].to_dict()

See the docs for to_dict. You can use it like this:

df.set_index('id').to_dict()

And if you have only one column, to avoid the column name is also a level in the dict (actually, in this case you use the Series.to_dict()):

df.set_index('id')['value'].to_dict()

回答 1

mydict = dict(zip(df.id, df.value))
mydict = dict(zip(df.id, df.value))

回答 2

如果您想要一种简单的方法来保留重复项,则可以使用groupby

>>> ptest = pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) 
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3
>>> {k: g["value"].tolist() for k,g in ptest.groupby("id")}
{'a': [1, 2], 'b': [3]}

If you want a simple way to preserve duplicates, you could use groupby:

>>> ptest = pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) 
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3
>>> {k: g["value"].tolist() for k,g in ptest.groupby("id")}
{'a': [1, 2], 'b': [3]}

回答 3

此线程中的joris和重复的线程中的punchagan的答案非常好,但是,如果用于键的列包含任何重复的值,它们将不会给出正确的结果。

例如:

>>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) 
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3

# note that in both cases the association a->1 is lost:
>>> ptest.set_index('id')['value'].to_dict()
{'a': 2, 'b': 3}
>>> dict(zip(ptest.id, ptest.value))
{'a': 2, 'b': 3}

如果您有重复的条目并且不想丢失它们,则可以使用以下难看但有效的代码:

>>> mydict = {}
>>> for x in range(len(ptest)):
...     currentid = ptest.iloc[x,0]
...     currentvalue = ptest.iloc[x,1]
...     mydict.setdefault(currentid, [])
...     mydict[currentid].append(currentvalue)
>>> mydict
{'a': [1, 2], 'b': [3]}

The answers by joris in this thread and by punchagan in the duplicated thread are very elegant, however they will not give correct results if the column used for the keys contains any duplicated value.

For example:

>>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) 
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3

# note that in both cases the association a->1 is lost:
>>> ptest.set_index('id')['value'].to_dict()
{'a': 2, 'b': 3}
>>> dict(zip(ptest.id, ptest.value))
{'a': 2, 'b': 3}

If you have duplicated entries and do not want to lose them, you can use this ugly but working code:

>>> mydict = {}
>>> for x in range(len(ptest)):
...     currentid = ptest.iloc[x,0]
...     currentvalue = ptest.iloc[x,1]
...     mydict.setdefault(currentid, [])
...     mydict[currentid].append(currentvalue)
>>> mydict
{'a': [1, 2], 'b': [3]}

回答 4

最简单的解决方案:

df.set_index('id').T.to_dict('records')

例:

df= pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id','value'])
df.set_index('id').T.to_dict('records')

如果您有多个值,例如val1,val2,val3等,并且您希望将它们作为列表,请使用以下代码:

df.set_index('id').T.to_dict('list')

Simplest solution:

df.set_index('id').T.to_dict('records')

Example:

df= pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id','value'])
df.set_index('id').T.to_dict('records')

If you have multiple values, like val1, val2, val3,etc and u want them as lists, then use the below code:

df.set_index('id').T.to_dict('list')

回答 5

在某些版本中,以下代码可能无法正常工作

mydict = dict(zip(df.id, df.value))

所以要明确

id_=df.id.values
value=df.value.values
mydict=dict(zip(id_,value))

注意我使用id_,因为单词id是保留单词

in some versions the code below might not work

mydict = dict(zip(df.id, df.value))

so make it explicit

id_=df.id.values
value=df.value.values
mydict=dict(zip(id_,value))

Note i used id_ because the word id is reserved word


回答 6

您可以使用“字典理解”

my_dict = {row[0]: row[1] for row in df.values}

You can use ‘dict comprehension’

my_dict = {row[0]: row[1] for row in df.values}

回答 7

另一个(略短)的解决方案,不会丢失重复的条目:

>>> ptest = pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id','value'])
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3

>>> pdict = dict()
>>> for i in ptest['id'].unique().tolist():
...     ptest_slice = ptest[ptest['id'] == i]
...     pdict[i] = ptest_slice['value'].tolist()
...

>>> pdict
{'b': [3], 'a': [1, 2]}

Another (slightly shorter) solution for not losing duplicate entries:

>>> ptest = pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id','value'])
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3

>>> pdict = dict()
>>> for i in ptest['id'].unique().tolist():
...     ptest_slice = ptest[ptest['id'] == i]
...     pdict[i] = ptest_slice['value'].tolist()
...

>>> pdict
{'b': [3], 'a': [1, 2]}

回答 8

您需要一个列表作为字典值。这段代码可以解决问题。

from collections import defaultdict
mydict = defaultdict(list)
for k, v in zip(df.id.values,df.value.values):
    mydict[k].append(v)

You need a list as a dictionary value. This code will do the trick.

from collections import defaultdict
mydict = defaultdict(list)
for k, v in zip(df.id.values,df.value.values):
    mydict[k].append(v)

回答 9

我试图从熊猫数据框的列中制作字典时发现了这个问题。在我的情况下,数据框具有A,B和C列(假设A和B是经度和纬度的地理坐标,C则是国家/地区/州/等等,或多或少是这种情况)。

我想要一个字典,其中每对A,B值(字典键)与对应行中的C(字典值)的值匹配(由于先前的过滤,每 A,B值保证是唯一的),但是它是在这种情况下,对于不同的A,B值对,可能具有相同的C值),所以我这样做了:

mydict = dict(zip(zip(df['A'],df['B']), df['C']))

使用熊猫to_dict()也可以:

mydict = df.set_index(['A','B']).to_dict(orient='dict')['C']

(在执行创建字典的行之前,A或B列均未用作索引)

两种方法都非常快速(在具有8万行,具有5年历史的快速双核笔记本电脑上,数据帧不到一秒钟)。

我发布此消息的原因:

  1. 对于那些需要这种解决方案的人
  2. 如果有人知道执行速度更快的解决方案(例如,数百万行),我将不胜感激。

I found this question while trying to make a dictionary out of three columns of a pandas dataframe. In my case the dataframe has columns A, B and C (let’s say A and B are the geographical coordinates of longitude and latitude and C the country region/state/etc, which is more or less the case).

I wanted a dictionary with each pair of A,B values (dictionary key) matching the value of C (dictionary value) in the corresponding row (each pair of A,B values is guaranteed to be unique due to previous filtering, but it is possible to have the same value of C for different pairs of A,B values in this context), so I did:

mydict = dict(zip(zip(df['A'],df['B']), df['C']))

Using pandas to_dict() also works:

mydict = df.set_index(['A','B']).to_dict(orient='dict')['C']

(none of the columns A or B were used as index before executing the line creating the dictionary)

Both approaches are fast (less than one second on a dataframe with 85k rows, 5-year-old fast dual-core laptop).

The reasons I’m posting this:

  1. for those who need this kind of solution
  2. if someone knows a faster executing solution (e.g., for millions of rows), I’d appreciate a reply.

回答 10

def get_dict_from_pd(df, key_col, row_col):
    result = dict()
    for i in set(df[key_col].values):
        is_i = df[key_col] == i
        result[i] = list(df[is_i][row_col].values)
    return result

这是我的想法,一个基本的循环

def get_dict_from_pd(df, key_col, row_col):
    result = dict()
    for i in set(df[key_col].values):
        is_i = df[key_col] == i
        result[i] = list(df[is_i][row_col].values)
    return result

this is my sloution, a basic loop


回答 11

这是我的解决方案:

import pandas as pd
df = pd.read_excel('dic.xlsx')
df_T = df.set_index('id').T
dic = df_T.to_dict('records')
print(dic)

This is my solution:

import pandas as pd
df = pd.read_excel('dic.xlsx')
df_T = df.set_index('id').T
dic = df_T.to_dict('records')
print(dic)

如何检查** kwargs键是否存在?

问题:如何检查** kwargs键是否存在?

Python 3.2.3。这里列出了一些想法,这些想法可以在常规var上使用,但是** kwargs似乎遵循不同的规则…所以,为什么这行不通?我如何检查** kwargs中的键是否存在?

if kwargs['errormessage']:
    print("It exists")

我也认为这应该可行,但是不-

if errormessage in kwargs:
    print("yeah it's here")

我猜是因为kwargs是可迭代的?我是否必须遍历它只是为了检查是否存在特定的密钥?

Python 3.2.3. There were some ideas listed here, which work on regular var’s, but it seems **kwargs play by different rules… so why doesn’t this work and how can I check to see if a key in **kwargs exists?

if kwargs['errormessage']:
    print("It exists")

I also think this should work, but it doesn’t —

if errormessage in kwargs:
    print("yeah it's here")

I’m guessing because kwargs is iterable? Do I have to iterate through it just to check if a particular key is there?


回答 0

你要

if 'errormessage' in kwargs:
    print("found it")

获得价值 errormessage

if 'errormessage' in kwargs:
    print("errormessage equals " + kwargs.get("errormessage"))

这样,kwargs只是另一个dict。您的第一个示例,if kwargs['errormessage']意思是“获取与kwargs中的键“ errormessage”关联的值,然后检查其bool值”。因此,如果没有这样的密钥,您将得到一个KeyError

您的第二个示例if errormessage in kwargs:表示“如果kwargs包含以”命名的元素errormessage,并且除非“ errormessage”是变量的名称,否则您将获得NameError

我应该提到的是,字典也有一个.get()接受默认参数的方法(本身默认为None),以便kwargs.get("errormessage")在该键存在时返回值,None否则返回值(类似地kwargs.get("errormessage", 17),您可能会认为这样做)。当您不关心键的存在与拥有None值或键不存在之间的区别时,这会很方便。

You want

if 'errormessage' in kwargs:
    print("found it")

To get the value of errormessage

if 'errormessage' in kwargs:
    print("errormessage equals " + kwargs.get("errormessage"))

In this way, kwargs is just another dict. Your first example, if kwargs['errormessage'], means “get the value associated with the key “errormessage” in kwargs, and then check its bool value”. So if there’s no such key, you’ll get a KeyError.

Your second example, if errormessage in kwargs:, means “if kwargs contains the element named by “errormessage“, and unless “errormessage” is the name of a variable, you’ll get a NameError.

I should mention that dictionaries also have a method .get() which accepts a default parameter (itself defaulting to None), so that kwargs.get("errormessage") returns the value if that key exists and None otherwise (similarly kwargs.get("errormessage", 17) does what you might think it does). When you don’t care about the difference between the key existing and having None as a value or the key not existing, this can be handy.


回答 1

DSM和Tadeck的答案将直接回答您的问题。

在我的脚本中,我经常使用便捷dict.pop()来处理可选参数和其他参数。这是一个简单print()包装器的示例:

def my_print(*args, **kwargs):
    prefix = kwargs.pop('prefix', '')
    print(prefix, *args, **kwargs)

然后:

>>> my_print('eggs')
 eggs
>>> my_print('eggs', prefix='spam')
spam eggs

如您所见,如果prefix中未包含kwargs,则默认值''(空字符串)存储在本地prefix变量中。如果给出,则使用其值。

对于编写任何类型的函数的包装程序,通常这是一个紧凑且易读的方法:始终只是传递您不了解的传递参数,甚至不知道它们是否存在。如果您总是通过,*args并且**kwargs使代码变慢,并且需要更多键入,但是如果被调用函数的接口(在这种情况下print)发生了变化,则无需更改代码。这种方法减少了开发时间,同时支持所有接口更改。

DSM’s and Tadeck’s answers answer your question directly.

In my scripts I often use the convenient dict.pop() to deal with optional, and additional arguments. Here’s an example of a simple print() wrapper:

def my_print(*args, **kwargs):
    prefix = kwargs.pop('prefix', '')
    print(prefix, *args, **kwargs)

Then:

>>> my_print('eggs')
 eggs
>>> my_print('eggs', prefix='spam')
spam eggs

As you can see, if prefix is not contained in kwargs, then the default '' (empty string) is being stored in the local prefix variable. If it is given, then its value is being used.

This is generally a compact and readable recipe for writing wrappers for any kind of function: Always just pass-through arguments you don’t understand, and don’t even know if they exist. If you always pass through *args and **kwargs you make your code slower, and requires a bit more typing, but if interfaces of the called function (in this case print) changes, you don’t need to change your code. This approach reduces development time while supporting all interface changes.


回答 2

就是这样:

if 'errormessage' in kwargs:
    print("yeah it's here")

您需要检查密钥是否在字典中。这样做的语法是some_key in some_dict(这里some_key是可哈希的,不一定是字符串)。

您链接的想法(这些想法)包含用于检查locals()and所返回的字典中是否存在特定键的示例globals()。您的示例与此类似,因为您正在检查kwargs字典(包含关键字参数的字典)中是否存在特定键。

It is just this:

if 'errormessage' in kwargs:
    print("yeah it's here")

You need to check, if the key is in the dictionary. The syntax for that is some_key in some_dict (where some_key is something hashable, not necessarily a string).

The ideas you have linked (these ideas) contained examples for checking if specific key existed in dictionaries returned by locals() and globals(). Your example is similar, because you are checking existence of specific key in kwargs dictionary (the dictionary containing keyword arguments).


回答 3

一种方法是自己添加!怎么样?通过合并kwargs一堆默认值。例如,如果您事先不知道密钥,则此方法不适用于所有情况。但是,如果有,这是一个简单的示例:

import sys

def myfunc(**kwargs):
    args = {'country':'England','town':'London',
            'currency':'Pound', 'language':'English'}

    diff = set(kwargs.keys()) - set(args.keys())
    if diff:
        print("Invalid args:",tuple(diff),file=sys.stderr)
        return

    args.update(kwargs)            
    print(args)

默认值在字典中设置,该字典args包括我们期望的所有键。我们首先检查kwarg中是否有任何意外的键。然后我们更新argskwargs,这将覆盖任何新的价值用户已设置。我们不需要测试键是否存在,我们现在将其args用作参数字典,并且不再需要kwargs

One way is to add it by yourself! How? By merging kwargs with a bunch of defaults. This won’t be appropriate on all occasions, for example, if the keys are not known to you in advance. However, if they are, here is a simple example:

import sys

def myfunc(**kwargs):
    args = {'country':'England','town':'London',
            'currency':'Pound', 'language':'English'}

    diff = set(kwargs.keys()) - set(args.keys())
    if diff:
        print("Invalid args:",tuple(diff),file=sys.stderr)
        return

    args.update(kwargs)            
    print(args)

The defaults are set in the dictionary args, which includes all the keys we are expecting. We first check to see if there are any unexpected keys in kwargs. Then we update args with kwargs which will overwrite any new values that the user has set. We don’t need to test if a key exists, we now use args as our argument dictionary and have no further need of kwargs.


回答 4

您可以自己轻松发现这些东西:

def hello(*args, **kwargs):
    print kwargs
    print type(kwargs)
    print dir(kwargs)

hello(what="world")

You can discover those things easily by yourself:

def hello(*args, **kwargs):
    print kwargs
    print type(kwargs)
    print dir(kwargs)

hello(what="world")

回答 5

if kwarg.__len__() != 0:
    print(kwarg)
if kwarg.__len__() != 0:
    print(kwarg)

遍历JSON对象

问题:遍历JSON对象

我正在尝试遍历JSON对象以导入数据,即标题和链接。我似乎无法掌握过去的内容:

JSON:

[
    {
        "title": "Baby (Feat. Ludacris) - Justin Bieber",
        "description": "Baby (Feat. Ludacris) by Justin Bieber on Grooveshark",
        "link": "http://listen.grooveshark.com/s/Baby+Feat+Ludacris+/2Bqvdq",
        "pubDate": "Wed, 28 Apr 2010 02:37:53 -0400",
        "pubTime": 1272436673,
        "TinyLink": "http://tinysong.com/d3wI",
        "SongID": "24447862",
        "SongName": "Baby (Feat. Ludacris)",
        "ArtistID": "1118876",
        "ArtistName": "Justin Bieber",
        "AlbumID": "4104002",
        "AlbumName": "My World (Part II);\nhttp://tinysong.com/gQsw",
        "LongLink": "11578982",
        "GroovesharkLink": "11578982",
        "Link": "http://tinysong.com/d3wI"
    },
    {
        "title": "Feel Good Inc - Gorillaz",
        "description": "Feel Good Inc by Gorillaz on Grooveshark",
        "link": "http://listen.grooveshark.com/s/Feel+Good+Inc/1UksmI",
        "pubDate": "Wed, 28 Apr 2010 02:25:30 -0400",
        "pubTime": 1272435930
    }
]

我尝试使用字典:

def getLastSong(user,limit):
    base_url = 'http://gsuser.com/lastSong/'
    user_url = base_url + str(user) + '/' + str(limit) + "/"
    raw = urllib.urlopen(user_url)
    json_raw= raw.readlines()
    json_object = json.loads(json_raw[0])

    #filtering and making it look good.
    gsongs = []
    print json_object
    for song in json_object[0]:   
        print song

此代码仅在之前打印信息:。(忽略贾斯汀·比伯的曲目:)

I am trying to iterate through a JSON object to import data, i.e. title and link. I can’t seem to get to the content that is past the :.

JSON:

[
    {
        "title": "Baby (Feat. Ludacris) - Justin Bieber",
        "description": "Baby (Feat. Ludacris) by Justin Bieber on Grooveshark",
        "link": "http://listen.grooveshark.com/s/Baby+Feat+Ludacris+/2Bqvdq",
        "pubDate": "Wed, 28 Apr 2010 02:37:53 -0400",
        "pubTime": 1272436673,
        "TinyLink": "http://tinysong.com/d3wI",
        "SongID": "24447862",
        "SongName": "Baby (Feat. Ludacris)",
        "ArtistID": "1118876",
        "ArtistName": "Justin Bieber",
        "AlbumID": "4104002",
        "AlbumName": "My World (Part II);\nhttp://tinysong.com/gQsw",
        "LongLink": "11578982",
        "GroovesharkLink": "11578982",
        "Link": "http://tinysong.com/d3wI"
    },
    {
        "title": "Feel Good Inc - Gorillaz",
        "description": "Feel Good Inc by Gorillaz on Grooveshark",
        "link": "http://listen.grooveshark.com/s/Feel+Good+Inc/1UksmI",
        "pubDate": "Wed, 28 Apr 2010 02:25:30 -0400",
        "pubTime": 1272435930
    }
]

I tried using a dictionary:

def getLastSong(user,limit):
    base_url = 'http://gsuser.com/lastSong/'
    user_url = base_url + str(user) + '/' + str(limit) + "/"
    raw = urllib.urlopen(user_url)
    json_raw= raw.readlines()
    json_object = json.loads(json_raw[0])

    #filtering and making it look good.
    gsongs = []
    print json_object
    for song in json_object[0]:   
        print song

This code only prints the information before :. (ignore the Justin Bieber track :))


回答 0

您加载JSON数据有些脆弱。代替:

json_raw= raw.readlines()
json_object = json.loads(json_raw[0])

您实际上应该这样做:

json_object = json.load(raw)

您不应该将“ JSON对象”视为什么。您所拥有的是清单。该列表包含两个字典。字典包含各种键/值对,所有字符串。当您这样做时json_object[0],您将要求列表中的第一个字典。当您使用进行迭代时for song in json_object[0]:,您将遍历字典的键。因为那是您遍历dict时得到的。如果要访问与该字典中的键关联的值,则可以使用json_object[0][song]

这些都不是特定于JSON的。这只是基本的Python类型,其基本操作如本教程所述。

Your loading of the JSON data is a little fragile. Instead of:

json_raw= raw.readlines()
json_object = json.loads(json_raw[0])

you should really just do:

json_object = json.load(raw)

You shouldn’t think of what you get as a “JSON object”. What you have is a list. The list contains two dicts. The dicts contain various key/value pairs, all strings. When you do json_object[0], you’re asking for the first dict in the list. When you iterate over that, with for song in json_object[0]:, you iterate over the keys of the dict. Because that’s what you get when you iterate over the dict. If you want to access the value associated with the key in that dict, you would use, for example, json_object[0][song].

None of this is specific to JSON. It’s just basic Python types, with their basic operations as covered in any tutorial.


回答 1

我相信您可能是说:

from __future__ import print_function

for song in json_object:
    # now song is a dictionary
    for attribute, value in song.items():
        print(attribute, value) # example usage

注意:您可以在Python 2中使用if song.iteritems代替song.items

I believe you probably meant:

from __future__ import print_function

for song in json_object:
    # now song is a dictionary
    for attribute, value in song.items():
        print(attribute, value) # example usage

NB: You could use song.iteritems instead of song.items if in Python 2.


回答 2

这个问题已经存在很长时间了,但是我想贡献我通常如何遍历JSON对象的方式。在下面的示例中,我显示了一个包含JSON的硬编码字符串,但是JSON字符串也可以很容易地来自Web服务或文件。

import json

def main():

    # create a simple JSON array
    jsonString = '{"key1":"value1","key2":"value2","key3":"value3"}'

    # change the JSON string into a JSON object
    jsonObject = json.loads(jsonString)

    # print the keys and values
    for key in jsonObject:
        value = jsonObject[key]
        print("The key and value are ({}) = ({})".format(key, value))

    pass

if __name__ == '__main__':
    main()

This question has been out here a long time, but I wanted to contribute how I usually iterate through a JSON object. In the example below, I’ve shown a hard-coded string that contains the JSON, but the JSON string could just as easily have come from a web service or a file.

import json

def main():

    # create a simple JSON array
    jsonString = '{"key1":"value1","key2":"value2","key3":"value3"}'

    # change the JSON string into a JSON object
    jsonObject = json.loads(jsonString)

    # print the keys and values
    for key in jsonObject:
        value = jsonObject[key]
        print("The key and value are ({}) = ({})".format(key, value))

    pass

if __name__ == '__main__':
    main()

回答 3

反序列化JSON之后,您将拥有一个python对象。使用常规对象方法。

在这种情况下,您有一个由字典组成的列表:

json_object[0].items()

json_object[0]["title"]

等等

After deserializing the JSON, you have a python object. Use the regular object methods.

In this case you have a list made of dictionaries:

json_object[0].items()

json_object[0]["title"]

etc.


回答 4

我会这样解决这个问题

import json
import urllib2

def last_song(user, limit):
    # Assembling strings with "foo" + str(bar) + "baz" + ... generally isn't 
    # as nice as using real string formatting. It can seem simpler at first, 
    # but leaves you less happy in the long run.
    url = 'http://gsuser.com/lastSong/%s/%d/' % (user, limit)

    # urllib.urlopen is deprecated in favour of urllib2.urlopen
    site = urllib2.urlopen(url)

    # The json module has a function load for loading from file-like objects, 
    # like the one you get from `urllib2.urlopen`. You don't need to turn 
    # your data into a string and use loads and you definitely don't need to 
    # use readlines or readline (there is seldom if ever reason to use a 
    # file-like object's readline(s) methods.)
    songs = json.load(site)

    # I don't know why "lastSong" stuff returns something like this, but 
    # your json thing was a JSON array of two JSON objects. This will 
    # deserialise as a list of two dicts, with each item representing 
    # each of those two songs.
    #
    # Since each of the songs is represented by a dict, it will iterate 
    # over its keys (like any other Python dict). 
    baby, feel_good = songs

    # Rather than printing in a function, it's usually better to 
    # return the string then let the caller do whatever with it. 
    # You said you wanted to make the output pretty but you didn't 
    # mention *how*, so here's an example of a prettyish representation
    # from the song information given.
    return "%(SongName)s by %(ArtistName)s - listen at %(link)s" % baby

I would solve this problem more like this

import json
import urllib2

def last_song(user, limit):
    # Assembling strings with "foo" + str(bar) + "baz" + ... generally isn't 
    # as nice as using real string formatting. It can seem simpler at first, 
    # but leaves you less happy in the long run.
    url = 'http://gsuser.com/lastSong/%s/%d/' % (user, limit)

    # urllib.urlopen is deprecated in favour of urllib2.urlopen
    site = urllib2.urlopen(url)

    # The json module has a function load for loading from file-like objects, 
    # like the one you get from `urllib2.urlopen`. You don't need to turn 
    # your data into a string and use loads and you definitely don't need to 
    # use readlines or readline (there is seldom if ever reason to use a 
    # file-like object's readline(s) methods.)
    songs = json.load(site)

    # I don't know why "lastSong" stuff returns something like this, but 
    # your json thing was a JSON array of two JSON objects. This will 
    # deserialise as a list of two dicts, with each item representing 
    # each of those two songs.
    #
    # Since each of the songs is represented by a dict, it will iterate 
    # over its keys (like any other Python dict). 
    baby, feel_good = songs

    # Rather than printing in a function, it's usually better to 
    # return the string then let the caller do whatever with it. 
    # You said you wanted to make the output pretty but you didn't 
    # mention *how*, so here's an example of a prettyish representation
    # from the song information given.
    return "%(SongName)s by %(ArtistName)s - listen at %(link)s" % baby

回答 5

通过JSON进行迭代,您可以使用以下代码:

json_object = json.loads(json_file)
for element in json_object: 
    for value in json_object['Name_OF_YOUR_KEY/ELEMENT']:
        print(json_object['Name_OF_YOUR_KEY/ELEMENT']['INDEX_OF_VALUE']['VALUE'])

for iterating through JSON you can use this:

json_object = json.loads(json_file)
for element in json_object: 
    for value in json_object['Name_OF_YOUR_KEY/ELEMENT']:
        print(json_object['Name_OF_YOUR_KEY/ELEMENT']['INDEX_OF_VALUE']['VALUE'])

回答 6

对于Python 3,您必须解码从Web服务器获取的数据。例如,我将数据解码为utf8,然后对其进行处理:

 # example of json data object group with two values of key id
jsonstufftest = '{'group':{'id':'2','id':'3'}}
 # always set your headers
headers = {'User-Agent': 'Moz & Woz'}
 # the url you are trying to load and get json from
url = 'http://www.cooljson.com/cooljson.json'
 # in python 3 you can build the request using request.Request
req = urllib.request.Request(url,None,headers)
 # try to connect or fail gracefully
try:
    response = urllib.request.urlopen(req) # new python 3 code -jc
except:
    exit('could not load page, check connection')
 # read the response and DECODE
html=response.read().decode('utf8') # new python3 code
 # now convert the decoded string into real JSON
loadedjson = json.loads(html)
 # print to make sure it worked
print (loadedjson) # works like a charm
 # iterate through each key value
for testdata in loadedjson['group']:
    print (accesscount['id']) # should print 2 then 3 if using test json

如果不解码,Python 3中将得到字节与字符串错误。

For Python 3, you have to decode the data you get back from the web server. For instance I decode the data as utf8 then deal with it:

 # example of json data object group with two values of key id
jsonstufftest = '{'group':{'id':'2','id':'3'}}
 # always set your headers
headers = {'User-Agent': 'Moz & Woz'}
 # the url you are trying to load and get json from
url = 'http://www.cooljson.com/cooljson.json'
 # in python 3 you can build the request using request.Request
req = urllib.request.Request(url,None,headers)
 # try to connect or fail gracefully
try:
    response = urllib.request.urlopen(req) # new python 3 code -jc
except:
    exit('could not load page, check connection')
 # read the response and DECODE
html=response.read().decode('utf8') # new python3 code
 # now convert the decoded string into real JSON
loadedjson = json.loads(html)
 # print to make sure it worked
print (loadedjson) # works like a charm
 # iterate through each key value
for testdata in loadedjson['group']:
    print (accesscount['id']) # should print 2 then 3 if using test json

If you don’t decode you will get bytes vs string errors in Python 3.


Python-从字典返回前N个key:value对

问题:Python-从字典返回前N个key:value对

考虑以下字典d:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

我想从d返回前N个key:value对(在这种情况下,N <= 4)。最有效的方法是什么?

Consider the following dictionary, d:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

I want to return the first N key:value pairs from d (N <= 4 in this case). What is the most efficient method of doing this?


回答 0

不需要“前n个”键,因为a dict不会记住首先插入的键。

你可以任意 n键-值对,但:

n_items = take(n, d.iteritems())

这使用take来自itertools配方的实现:

from itertools import islice

def take(n, iterable):
    "Return first n items of the iterable as a list"
    return list(islice(iterable, n))

看到它在线上工作:ideone


Python 3.6更新

n_items = take(n, d.items())

There’s no such thing a the “first n” keys because a dict doesn’t remember which keys were inserted first.

You can get any n key-value pairs though:

n_items = take(n, d.iteritems())

This uses the implementation of take from the itertools recipes:

from itertools import islice

def take(n, iterable):
    "Return first n items of the iterable as a list"
    return list(islice(iterable, n))

See it working online: ideone


Update for Python 3.6

n_items = take(n, d.items())

回答 1

检索任何内容的一种非常有效的方法是将列表或字典理解与切片结合在一起。如果您不需要订购商品(您只需要n个随机对),则可以使用如下的字典理解:

# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}

通常,这样的理解总是比等效的“ for y中的x”循环要快。另外,通过使用.keys()创建字典关键字列表并对该列表进行切片,可以避免在构建新字典时“触摸”任何不必要的关键字。

如果不需要键(仅值),则可以使用列表推导:

first2vals = [v for v in mydict.values()[:2]]

如果您需要根据其键对值进行排序,那么麻烦就不多了:

first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]

或者,如果您还需要按键:

first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}

A very efficient way to retrieve anything is to combine list or dictionary comprehensions with slicing. If you don’t need to order the items (you just want n random pairs), you can use a dictionary comprehension like this:

# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}

Generally a comprehension like this is always faster to run than the equivalent “for x in y” loop. Also, by using .keys() to make a list of the dictionary keys and slicing that list you avoid ‘touching’ any unnecessary keys when you build the new dictionary.

If you don’t need the keys (only the values) you can use a list comprehension:

first2vals = [v for v in mydict.values()[:2]]

If you need the values sorted based on their keys, it’s not much more trouble:

first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]

or if you need the keys as well:

first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}

回答 2

Python的dict不排序,因此要求“前N个”键毫无意义。

collections.OrderedDict如果您需要,可以使用该类。您可以有效地获得其前四个要素

import itertools
import collections

d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')))
x = itertools.islice(d.items(), 0, 4)

for key, value in x:
    print key, value

itertools.islice允许您懒惰地从任何迭代器中获取元素的一部分。如果您希望结果可重用,则需要将其转换为列表或类似内容,例如:

x = list(itertools.islice(d.items(), 0, 4))

Python’s dicts are not ordered, so it’s meaningless to ask for the “first N” keys.

The collections.OrderedDict class is available if that’s what you need. You could efficiently get its first four elements as

import itertools
import collections

d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')))
x = itertools.islice(d.items(), 0, 4)

for key, value in x:
    print key, value

itertools.islice allows you to lazily take a slice of elements from any iterator. If you want the result to be reusable you’d need to convert it to a list or something, like so:

x = list(itertools.islice(d.items(), 0, 4))

回答 3

foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
iterator = iter(foo.items())
for i in range(3):
    print(next(iterator))

基本上,将视图(dict_items)变成一个迭代器,然后使用next()对其进行迭代。

foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
iterator = iter(foo.items())
for i in range(3):
    print(next(iterator))

Basically, turn the view (dict_items) into an iterator, and then iterate it with next().


回答 4

在这里没有看到它。如果只需要从字典中提取某些元素,则不会在语法上排序,而是从语法上最简单。

n = 2
{key:value for key,value in d.items()[0:n]}

Did not see it on here. Will not be ordered but the simplest syntactically if you need to just take some elements from a dictionary.

n = 2
{key:value for key,value in d.items()[0:n]}

回答 5

要从python字典中获取前N个元素,可以使用以下代码行:

list(dictionaryName.items())[:N]

您可以将其更改为:

list(d.items())[:4]

To get the top N elements from your python dictionary one can use the following line of code:

list(dictionaryName.items())[:N]

In your case you can change it to:

list(d.items())[:4]

回答 6

参见PEP 0265有关对字典进行排序。然后使用前面提到的可迭代代码。

如果您需要更高效率的已排序键值对。使用不同的数据结构。也就是说,它保持排序顺序和键值关联。

例如

import bisect

kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)]
bisect.insort_left(kvlist, ('d', 4))

print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

See PEP 0265 on sorting dictionaries. Then use the aforementioned iterable code.

If you need more efficiency in the sorted key-value pairs. Use a different data structure. That is, one that maintains sorted order and the key-value associations.

E.g.

import bisect

kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)]
bisect.insort_left(kvlist, ('d', 4))

print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

回答 7

在py3中,这可以解决问题

{A:N for (A,N) in [x for x in d.items()][:4]}

{‘a’:3,’b’:2,’c’:3,’d’:4}

in py3, this will do the trick

{A:N for (A,N) in [x for x in d.items()][:4]}

{‘a’: 3, ‘b’: 2, ‘c’: 3, ‘d’: 4}


回答 8

只需使用zip添加答案,

{k: d[k] for k, _ in zip(d, range(n))}

just add an answer using zip,

{k: d[k] for k, _ in zip(d, range(n))}

回答 9

这取决于您的情况下“最有效”的方法。

如果您只想要一个巨大词典的半随机样本foofoo.iteritems()并根据需要使用它并从中获取尽可能多的值,那么这是一个懒惰的操作,可以避免创建键或项的显式列表。

如果您需要先对键进行排序,则无法使用keys = foo.keys(); keys.sort()sorted(foo.iterkeys())来构建键的显式列表。然后对第一个N进行切片或迭代keys

顺便说一句,您为什么关心“有效”方式?您是否对程序进行了简介?如果您没有这样做,请首先使用明显易于理解的方法。它很有可能在不成为瓶颈的情况下做得很好。

This depends on what is ‘most efficient’ in your case.

If you just want a semi-random sample of a huge dictionary foo, use foo.iteritems() and take as many values from it as you need, it’s a lazy operation that avoids creation of an explicit list of keys or items.

If you need to sort keys first, there’s no way around using something like keys = foo.keys(); keys.sort() or sorted(foo.iterkeys()), you’ll have to build an explicit list of keys. Then slice or iterate through first N keys.

BTW why do you care about the ‘efficient’ way? Did you profile your program? If you did not, use the obvious and easy to understand way first. Chances are it will do pretty well without becoming a bottleneck.


回答 10

您可以通过多种方法来实现。如果订单很重要,则可以执行以下操作:

for key in sorted(d.keys()):
  item = d.pop(key)

如果不需要订购,可以执行以下操作:

for i in range(4):
  item = d.popitem()

You can approach this a number of ways. If order is important you can do this:

for key in sorted(d.keys()):
  item = d.pop(key)

If order isn’t a concern you can do this:

for i in range(4):
  item = d.popitem()

回答 11

字典没有顺序,因此在选择前N个键值对之前,先对其进行排序。

import operator
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
#itemgetter(0)=sort by keys, itemgetter(1)=sort by values

现在,我们可以使用以下方法结构来检索前N个元素:

def return_top(elements,dictionary_element):
    '''Takes the dictionary and the 'N' elements needed in return
    '''
    topers={}
    for h,i in enumerate(dictionary_element):
        if h<elements:
            topers.update({i:dictionary_element[i]})
    return topers

要获得前2个元素,则只需使用以下结构:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
d=return_top(2,d)
print(d)

Dictionary maintains no order , so before picking top N key value pairs lets make it sorted.

import operator
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
#itemgetter(0)=sort by keys, itemgetter(1)=sort by values

Now we can do the retrieval of top ‘N’ elements:, using the method structure like this:

def return_top(elements,dictionary_element):
    '''Takes the dictionary and the 'N' elements needed in return
    '''
    topers={}
    for h,i in enumerate(dictionary_element):
        if h<elements:
            topers.update({i:dictionary_element[i]})
    return topers

to get the top 2 elements then simply use this structure:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
d=return_top(2,d)
print(d)

回答 12

对于Python 3及更高版本,要选择前n对

n=4
firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}

For Python 3 and above,To select first n Pairs

n=4
firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}

回答 13

考虑一个命令

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

from itertools import islice
n = 3
list(islice(d.items(),n))

islice可以解决问题:)希望能有所帮助!

consider a dict

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

from itertools import islice
n = 3
list(islice(d.items(),n))

islice will do the trick :) hope it helps !


回答 14

这可能不是很优雅,但是对我有用:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

x= 0
for key, val in d.items():
    if x == 2:
        break
    else:
        x += 1
        # Do something with the first two key-value pairs

This might not be very elegant, but works for me:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

x= 0
for key, val in d.items():
    if x == 2:
        break
    else:
        x += 1
        # Do something with the first two key-value pairs

回答 15

我已经尝试了上面的一些答案,并注意到其中一些是依赖于版本的,并且在3.7版中不起作用。

我还注意到,自3.6起,所有字典均按插入项的顺序排序。

尽管从3.6版开始就对字典进行了排序,但是您希望使用有序结构的某些语句似乎不起作用。

最适合我的OP问题的答案。

itr = iter(dic.items())
lst = [next(itr) for i in range(3)]

I have tried a few of the answers above and note that some of them are version dependent and do not work in version 3.7.

I also note that since 3.6 all dictionaries are ordered by the sequence in which items are inserted.

Despite dictionaries being ordered since 3.6 some of the statements you expect to work with ordered structures don’t seem to work.

The answer to the OP question that worked best for me.

itr = iter(dic.items())
lst = [next(itr) for i in range(3)]

如果不存在,Python将更新dict中的键

问题:如果不存在,Python将更新dict中的键

如果键不在dict.keys()中,我想将一个键值对插入dict中。基本上我可以做到:

if key not in d.keys():
    d[key] = value

但是有更好的方法吗?或针对此问题的pythonic解决方案是什么?

I want to insert a key-value pair into dict if key not in dict.keys(). Basically I could do it with:

if key not in d.keys():
    d[key] = value

But is there a better way? Or what’s the pythonic solution to this problem?


回答 0

您无需调用d.keys(),因此

if key not in d:
    d[key] = value

足够的。没有更清晰,更易读的方法。

您可以使用再次更新dict.get(),如果键已经存在,它将返回一个现有值:

d[key] = d.get(key, value)

但我强烈建议您反对;这是代码打高尔夫球,妨碍了维护和可读性。

You do not need to call d.keys(), so

if key not in d:
    d[key] = value

is enough. There is no clearer, more readable method.

You could update again with dict.get(), which would return an existing value if the key is already present:

d[key] = d.get(key, value)

but I strongly recommend against this; this is code golfing, hindering maintenance and readability.


回答 1

用途dict.setdefault()

>>> d = {1: 'one'}
>>> d.setdefault(1, '1')
'one'
>>> d    # d has not changed because the key already existed
{1: 'one'}
>>> d.setdefault(2, 'two')
'two'
>>> d
{1: 'one', 2: 'two'}

Use dict.setdefault():

>>> d = {1: 'one'}
>>> d.setdefault(1, '1')
'one'
>>> d    # d has not changed because the key already existed
{1: 'one'}
>>> d.setdefault(2, 'two')
'two'
>>> d
{1: 'one', 2: 'two'}

回答 2

Python 3.9开始,您可以使用merge运算 |符合并两个字典。右侧的dict优先:

new_dict = old_dict | { key: val }

例如:

new_dict = { 'a': 1, 'b': 2 } | { 'b': 42 }

print(new_dict} # {'a': 1, 'b': 42}

注意:这将创建具有更新值的新字典。

Since Python 3.9 you can use the merge operator | to merge two dictionaries. The dict on the right takes precedence:

d = { key: value } | d

Note: this creates a new dictionary with the updated values.


回答 3

使用以下代码,您可以插入多个值,也可以使用默认值,但是您正在创建一个新字典。

d = {**{ key: value }, **default_values}

我已经用投票率最高的答案对其进行了测试,平均而言,这样做的速度更快,如下面的示例所示。

速度测试将基于for循环的方法与带有unpack运算符的dict理解进行比较 速度测试将基于for循环的方法与带有unpack运算符方法的dict理解进行比较。

如果d = default_vals.copy()在第一种情况下没有复制(),则一旦我们达到10**5或更大的数量级,投票最多的答案就会更快。两种方法的内存占用相同。

With the following you can insert multiple values and also have default values but you’re creating a new dictionary.

d = {**{ key: value }, **default_values}

I’ve tested it with the most voted answer and on average this is faster as it can be seen in the following example, .

Speed test comparing a for loop based method with a dict comprehension with unpack operator Speed test comparing a for loop based method with a dict comprehension with unpack operator method.

if no copy (d = default_vals.copy()) is made on the first case then the most voted answer would be faster once we reach orders of magnitude of 10**5 and greater. Memory footprint of both methods are the same.


回答 4

根据以上答案,setdefault()方法为我工作。

old_attr_name = mydict.setdefault(key, attr_name)
if attr_name != old_attr_name:
    raise RuntimeError(f"Key '{key}' duplication: "
                       f"'{old_attr_name}' and '{attr_name}'.")

虽然此解决方案不是通用的。在这种情况下才适合我。确切的解决方案是检查第key一个(如已经建议的),但是setdefault()我们避免在字典上进行额外的查找,即虽然很小,但仍然可以提高性能。

According to the above answers setdefault() method worked for me.

old_attr_name = mydict.setdefault(key, attr_name)
if attr_name != old_attr_name:
    raise RuntimeError(f"Key '{key}' duplication: "
                       f"'{old_attr_name}' and '{attr_name}'.")

Though this solution is not generic. Just suited me in this certain case. The exact solution would be checking for the key first (as was already advised), but with setdefault() we avoid one extra lookup on the dictionary, that is, though small, but still a performance gain.


定义type.Dict和dict之间的区别?

问题:定义type.Dict和dict之间的区别?

我正在练习在Python 3.5中使用类型提示。我的一位同事使用typing.Dict

import typing


def change_bandwidths(new_bandwidths: typing.Dict,
                      user_id: int,
                      user_name: str) -> bool:
    print(new_bandwidths, user_id, user_name)
    return False


def my_change_bandwidths(new_bandwidths: dict,
                         user_id: int,
                         user_name: str) ->bool:
    print(new_bandwidths, user_id, user_name)
    return True


def main():
    my_id, my_name = 23, "Tiras"
    simple_dict = {"Hello": "Moon"}
    change_bandwidths(simple_dict, my_id, my_name)
    new_dict = {"new": "energy source"}
    my_change_bandwidths(new_dict, my_id, my_name)

if __name__ == "__main__":
    main()

他们两个都工作得很好,似乎没有什么区别。

我已经阅读了typing模块文档

之间typing.Dictdict哪一个,我应该在程序中使用?

I am practicing using type hints in Python 3.5. One of my colleague uses typing.Dict:

import typing


def change_bandwidths(new_bandwidths: typing.Dict,
                      user_id: int,
                      user_name: str) -> bool:
    print(new_bandwidths, user_id, user_name)
    return False


def my_change_bandwidths(new_bandwidths: dict,
                         user_id: int,
                         user_name: str) ->bool:
    print(new_bandwidths, user_id, user_name)
    return True


def main():
    my_id, my_name = 23, "Tiras"
    simple_dict = {"Hello": "Moon"}
    change_bandwidths(simple_dict, my_id, my_name)
    new_dict = {"new": "energy source"}
    my_change_bandwidths(new_dict, my_id, my_name)

if __name__ == "__main__":
    main()

Both of them work just fine, there doesn’t appear to be a difference.

I have read the typing module documentation.

Between typing.Dict or dict which one should I use in the program?


回答 0

使用Plaintyping.DictdictNo之间没有真正的区别。

然而,typing.Dict是一种通用型 *,可让您指定键和值的类型太多,使之更加灵活:

def change_bandwidths(new_bandwidths: typing.Dict[str, str],
                      user_id: int,
                      user_name: str) -> bool:

因此,很可能是在项目生命周期中的某个时候,您希望更精确地定义字典参数,在这一点上,扩展typing.Dicttyping.Dict[key_type, value_type]而不是替换是“更小的”改变dict

您可以通过在此处使用MappingMutableMapping类型来使其更通用。由于您的函数不需要更改映射,因此我坚持使用Mapping。Adict是一个映射,但是您可以创建也满足映射接口的其他对象,并且您的函数可能仍可以与那些对象一起使用:

def change_bandwidths(new_bandwidths: typing.Mapping[str, str],
                      user_id: int,
                      user_name: str) -> bool:

现在,您清楚地告诉此功能的其他用户,您的代码实际上不会更改new_bandwidths传入的映射。

您的实际实现只是期望一个可打印的对象。那可能是一个测试实现,但是就目前而言,如果使用new_bandwidths: typing.Any,您的代码将继续工作,因为Python中的任何对象都是可打印的。


*:注意:如果您使用的是Python 3.7或更高版本,则使用dict开头的模块即可将其用作通用类型from __future__ import annotations,而从python 3.9开始,dict(以及其他标准容器)也支持将其用作通用类型。指令

There is no real difference between using a plain typing.Dict and dict, no.

However, typing.Dict is a Generic type that lets you specify the type of the keys and values too, making it more flexible:

def change_bandwidths(new_bandwidths: typing.Dict[str, str],
                      user_id: int,
                      user_name: str) -> bool:

As such, it could well be that at some point in your project lifetime you want to define the dictionary argument a little more precisely, at which point expanding typing.Dict to typing.Dict[key_type, value_type] is a ‘smaller’ change than replacing dict.

You can make this even more generic by using Mapping or MutableMapping types here; since your function doesn’t need to alter the mapping, I’d stick with Mapping. A dict is one mapping, but you could create other objects that also satisfy the mapping interface, and your function might well still work with those:

def change_bandwidths(new_bandwidths: typing.Mapping[str, str],
                      user_id: int,
                      user_name: str) -> bool:

Now you are clearly telling other users of this function that your code won’t actually alter the new_bandwidths mapping passed in.

Your actual implementation is merely expecting an object that is printable. That may be a test implementation, but as it stands your code would continue to work if you used new_bandwidths: typing.Any, because any object in Python is printable.


回答 1

typing.Dict是以下内容的通用版本dict

class typing.Dict(dict, MutableMapping[KT, VT])

dict的通用版本。此类型的用法如下:

def get_position_in_index(word_list: Dict[str, int], word: str) -> int:
     return word_list[word]

在这里,您可以在dict中指定键和值的类型: Dict[str, int]

typing.Dict is a generic version of dict:

class typing.Dict(dict, MutableMapping[KT, VT])

A generic version of dict. The usage of this type is as follows:

def get_position_in_index(word_list: Dict[str, int], word: str) -> int:
     return word_list[word]

Here you can specify the type of key and values in the dict: Dict[str, int]


Python:将元组/字典作为键,进行选择,排序

问题:Python:将元组/字典作为键,进行选择,排序

假设我有大量不同颜色的水果,例如24个蓝色香蕉,12个绿色苹果,0个蓝色草莓等等。我想将它们组织成Python的数据结构,以便于选择和排序。我的想法是将它们放入以元组为键的字典中,例如,

{ ('banana',    'blue' ): 24,
  ('apple',     'green'): 12,
  ('strawberry','blue' ): 0,
  ...
}

甚至字典,例如

{ {'fruit': 'banana',    'color': 'blue' }: 24,
  {'fruit': 'apple',     'color': 'green'}: 12,
  {'fruit': 'strawberry','color': 'blue' }: 0,
  ...
}

例如,我想检索所有蓝色水果或所有颜色的香蕉的列表,或按水果名称对这本词典进行排序。有没有办法做到这一点?

用元组作为键的字典可能不是处理这种情况的正确方法。

欢迎所有建议!

Suppose I have quantities of fruits of different colors, e.g., 24 blue bananas, 12 green apples, 0 blue strawberries and so on. I’d like to organize them in a data structure in Python that allows for easy selection and sorting. My idea was to put them into a dictionary with tuples as keys, e.g.,

{
    ('banana',    'blue' ): 24,
    ('apple',     'green'): 12,
    ('strawberry','blue' ): 0,
    # ...
}

or even dictionaries, e.g.,

{
    {'fruit': 'banana',    'color': 'blue' }: 24,
    {'fruit': 'apple',     'color': 'green'}: 12,
    {'fruit': 'strawberry','color': 'blue' }: 0,
    # ...
}

I’d like to retrieve a list of all blue fruit, or bananas of all colors, for example, or to sort this dictionary by the name of the fruit. Are there ways to do this in a clean way?

It might well be that dictionaries with tuples as keys are not the proper way to handle this situation.

All suggestions welcome!


回答 0

就个人而言,我喜欢python的一件事是tuple-dict组合。您在这里拥有的实际上是一个2d数组(其中x =水果名称,y =颜色),而且我通常是实现2d数组的元组字典的支持者,至少在诸如之类numpy的数据库不适合使用时。简而言之,我认为您有一个很好的方法。

请注意,如果不做一些额外的工作,就不能将字典用作字典中的键,因此这不是一个很好的解决方案。

也就是说,您还应该考虑namedtuple()。这样,您可以执行以下操作:

>>> from collections import namedtuple
>>> Fruit = namedtuple("Fruit", ["name", "color"])
>>> f = Fruit(name="banana", color="red")
>>> print f
Fruit(name='banana', color='red')
>>> f.name
'banana'
>>> f.color
'red'

现在您可以使用fruitcount字典:

>>> fruitcount = {Fruit("banana", "red"):5}
>>> fruitcount[f]
5

其他技巧:

>>> fruits = fruitcount.keys()
>>> fruits.sort()
>>> print fruits
[Fruit(name='apple', color='green'), 
 Fruit(name='apple', color='red'), 
 Fruit(name='banana', color='blue'), 
 Fruit(name='strawberry', color='blue')]
>>> fruits.sort(key=lambda x:x.color)
>>> print fruits
[Fruit(name='banana', color='blue'), 
 Fruit(name='strawberry', color='blue'), 
 Fruit(name='apple', color='green'), 
 Fruit(name='apple', color='red')]

与chmullig相呼应,要获得一个水果的所有颜色的列表,您必须过滤键,即

bananas = [fruit for fruit in fruits if fruit.name=='banana']

Personally, one of the things I love about python is the tuple-dict combination. What you have here is effectively a 2d array (where x = fruit name and y = color), and I am generally a supporter of the dict of tuples for implementing 2d arrays, at least when something like numpy or a database isn’t more appropriate. So in short, I think you’ve got a good approach.

Note that you can’t use dicts as keys in a dict without doing some extra work, so that’s not a very good solution.

That said, you should also consider namedtuple(). That way you could do this:

>>> from collections import namedtuple
>>> Fruit = namedtuple("Fruit", ["name", "color"])
>>> f = Fruit(name="banana", color="red")
>>> print f
Fruit(name='banana', color='red')
>>> f.name
'banana'
>>> f.color
'red'

Now you can use your fruitcount dict:

>>> fruitcount = {Fruit("banana", "red"):5}
>>> fruitcount[f]
5

Other tricks:

>>> fruits = fruitcount.keys()
>>> fruits.sort()
>>> print fruits
[Fruit(name='apple', color='green'), 
 Fruit(name='apple', color='red'), 
 Fruit(name='banana', color='blue'), 
 Fruit(name='strawberry', color='blue')]
>>> fruits.sort(key=lambda x:x.color)
>>> print fruits
[Fruit(name='banana', color='blue'), 
 Fruit(name='strawberry', color='blue'), 
 Fruit(name='apple', color='green'), 
 Fruit(name='apple', color='red')]

Echoing chmullig, to get a list of all colors of one fruit, you would have to filter the keys, i.e.

bananas = [fruit for fruit in fruits if fruit.name=='banana']

回答 1

最好的选择是创建一个简单的数据结构来对您所拥有的进行建模。然后,您可以将这些对象存储在一个简单的列表中,并根据需要进行排序/检索。

对于这种情况,我将使用以下类:

class Fruit:
    def __init__(self, name, color, quantity): 
        self.name = name
        self.color = color
        self.quantity = quantity

    def __str__(self):
        return "Name: %s, Color: %s, Quantity: %s" % \
     (self.name, self.color, self.quantity)

然后,您可以简单地构造“ Fruit”实例并将其添加到列表中,如下所示:

fruit1 = Fruit("apple", "red", 12)
fruit2 = Fruit("pear", "green", 22)
fruit3 = Fruit("banana", "yellow", 32)
fruits = [fruit3, fruit2, fruit1] 

简单的列表fruits将更加容易,混乱并且维护得更好。

一些使用示例:

下面的所有输出是运行给定代码段后的结果:

for fruit in fruits:
    print fruit

未排序清单:

显示:

Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22
Name: apple, Color: red, Quantity: 12

按名称按字母顺序排序:

fruits.sort(key=lambda x: x.name.lower())

显示:

Name: apple, Color: red, Quantity: 12
Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22

按数量排序:

fruits.sort(key=lambda x: x.quantity)

显示:

Name: apple, Color: red, Quantity: 12
Name: pear, Color: green, Quantity: 22
Name: banana, Color: yellow, Quantity: 32

颜色==红色:

red_fruit = filter(lambda f: f.color == "red", fruits)

显示:

Name: apple, Color: red, Quantity: 12

Your best option will be to create a simple data structure to model what you have. Then you can store these objects in a simple list and sort/retrieve them any way you wish.

For this case, I’d use the following class:

class Fruit:
    def __init__(self, name, color, quantity): 
        self.name = name
        self.color = color
        self.quantity = quantity

    def __str__(self):
        return "Name: %s, Color: %s, Quantity: %s" % \
     (self.name, self.color, self.quantity)

Then you can simply construct “Fruit” instances and add them to a list, as shown in the following manner:

fruit1 = Fruit("apple", "red", 12)
fruit2 = Fruit("pear", "green", 22)
fruit3 = Fruit("banana", "yellow", 32)
fruits = [fruit3, fruit2, fruit1] 

The simple list fruits will be much easier, less confusing, and better-maintained.

Some examples of use:

All outputs below is the result after running the given code snippet followed by:

for fruit in fruits:
    print fruit

Unsorted list:

Displays:

Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22
Name: apple, Color: red, Quantity: 12

Sorted alphabetically by name:

fruits.sort(key=lambda x: x.name.lower())

Displays:

Name: apple, Color: red, Quantity: 12
Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22

Sorted by quantity:

fruits.sort(key=lambda x: x.quantity)

Displays:

Name: apple, Color: red, Quantity: 12
Name: pear, Color: green, Quantity: 22
Name: banana, Color: yellow, Quantity: 32

Where color == red:

red_fruit = filter(lambda f: f.color == "red", fruits)

Displays:

Name: apple, Color: red, Quantity: 12

回答 2

数据库,词典的字典,词典列表的字典,命名为tuple(这是一个子类),sqlite,冗余…我不敢相信自己的眼睛。还有什么 ?

“很可能以元组为键的字典不是处理这种情况的正确方法。”

“我的直觉是数据库对于OP的需求而言是过大的;”

是的 我想

因此,我认为,一个元组列表就足够了:

from operator import itemgetter

li = [  ('banana',     'blue'   , 24) ,
        ('apple',      'green'  , 12) ,
        ('strawberry', 'blue'   , 16 ) ,
        ('banana',     'yellow' , 13) ,
        ('apple',      'gold'   , 3 ) ,
        ('pear',       'yellow' , 10) ,
        ('strawberry', 'orange' , 27) ,
        ('apple',      'blue'   , 21) ,
        ('apple',      'silver' , 0 ) ,
        ('strawberry', 'green'  , 4 ) ,
        ('banana',     'brown'  , 14) ,
        ('strawberry', 'yellow' , 31) ,
        ('apple',      'pink'   , 9 ) ,
        ('strawberry', 'gold'   , 0 ) ,
        ('pear',       'gold'   , 66) ,
        ('apple',      'yellow' , 9 ) ,
        ('pear',       'brown'  , 5 ) ,
        ('strawberry', 'pink'   , 8 ) ,
        ('apple',      'purple' , 7 ) ,
        ('pear',       'blue'   , 51) ,
        ('chesnut',    'yellow',  0 )   ]


print set( u[1] for u in li ),': all potential colors'
print set( c for f,c,n in li if n!=0),': all effective colors'
print [ c for f,c,n in li if f=='banana' ],': all potential colors of bananas'
print [ c for f,c,n in li if f=='banana' and n!=0],': all effective colors of bananas'
print

print set( u[0] for u in li ),': all potential fruits'
print set( f for f,c,n in li if n!=0),': all effective fruits'
print [ f for f,c,n in li if c=='yellow' ],': all potential fruits being yellow'
print [ f for f,c,n in li if c=='yellow' and n!=0],': all effective fruits being yellow'
print

print len(set( u[1] for u in li )),': number of all potential colors'
print len(set(c for f,c,n in li if n!=0)),': number of all effective colors'
print len( [c for f,c,n in li if f=='strawberry']),': number of potential colors of strawberry'
print len( [c for f,c,n in li if f=='strawberry' and n!=0]),': number of effective colors of strawberry'
print

# sorting li by name of fruit
print sorted(li),'  sorted li by name of fruit'
print

# sorting li by number 
print sorted(li, key = itemgetter(2)),'  sorted li by number'
print

# sorting li first by name of color and secondly by name of fruit
print sorted(li, key = itemgetter(1,0)),'  sorted li first by name of color and secondly by name of fruit'
print

结果

set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange', 'silver']) : all potential colors
set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange']) : all effective colors
['blue', 'yellow', 'brown'] : all potential colors of bananas
['blue', 'yellow', 'brown'] : all effective colors of bananas

set(['strawberry', 'chesnut', 'pear', 'banana', 'apple']) : all potential fruits
set(['strawberry', 'pear', 'banana', 'apple']) : all effective fruits
['banana', 'pear', 'strawberry', 'apple', 'chesnut'] : all potential fruits being yellow
['banana', 'pear', 'strawberry', 'apple'] : all effective fruits being yellow

9 : number of all potential colors
8 : number of all effective colors
6 : number of potential colors of strawberry
5 : number of effective colors of strawberry

[('apple', 'blue', 21), ('apple', 'gold', 3), ('apple', 'green', 12), ('apple', 'pink', 9), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'blue', 24), ('banana', 'brown', 14), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'blue', 51), ('pear', 'brown', 5), ('pear', 'gold', 66), ('pear', 'yellow', 10), ('strawberry', 'blue', 16), ('strawberry', 'gold', 0), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('strawberry', 'pink', 8), ('strawberry', 'yellow', 31)]   sorted li by name of fruit

[('apple', 'silver', 0), ('strawberry', 'gold', 0), ('chesnut', 'yellow', 0), ('apple', 'gold', 3), ('strawberry', 'green', 4), ('pear', 'brown', 5), ('apple', 'purple', 7), ('strawberry', 'pink', 8), ('apple', 'pink', 9), ('apple', 'yellow', 9), ('pear', 'yellow', 10), ('apple', 'green', 12), ('banana', 'yellow', 13), ('banana', 'brown', 14), ('strawberry', 'blue', 16), ('apple', 'blue', 21), ('banana', 'blue', 24), ('strawberry', 'orange', 27), ('strawberry', 'yellow', 31), ('pear', 'blue', 51), ('pear', 'gold', 66)]   sorted li by number

[('apple', 'blue', 21), ('banana', 'blue', 24), ('pear', 'blue', 51), ('strawberry', 'blue', 16), ('banana', 'brown', 14), ('pear', 'brown', 5), ('apple', 'gold', 3), ('pear', 'gold', 66), ('strawberry', 'gold', 0), ('apple', 'green', 12), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('apple', 'pink', 9), ('strawberry', 'pink', 8), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'yellow', 10), ('strawberry', 'yellow', 31)]   sorted li first by name of color and secondly by name of fruit

Database, dict of dicts, dictionary of list of dictionaries, named tuple (it’s a subclass), sqlite, redundancy… I didn’t believe my eyes. What else ?

“It might well be that dictionaries with tuples as keys are not the proper way to handle this situation.”

“my gut feeling is that a database is overkill for the OP’s needs; “

Yeah! I thought

So, in my opinion, a list of tuples is plenty enough :

from operator import itemgetter

li = [  ('banana',     'blue'   , 24) ,
        ('apple',      'green'  , 12) ,
        ('strawberry', 'blue'   , 16 ) ,
        ('banana',     'yellow' , 13) ,
        ('apple',      'gold'   , 3 ) ,
        ('pear',       'yellow' , 10) ,
        ('strawberry', 'orange' , 27) ,
        ('apple',      'blue'   , 21) ,
        ('apple',      'silver' , 0 ) ,
        ('strawberry', 'green'  , 4 ) ,
        ('banana',     'brown'  , 14) ,
        ('strawberry', 'yellow' , 31) ,
        ('apple',      'pink'   , 9 ) ,
        ('strawberry', 'gold'   , 0 ) ,
        ('pear',       'gold'   , 66) ,
        ('apple',      'yellow' , 9 ) ,
        ('pear',       'brown'  , 5 ) ,
        ('strawberry', 'pink'   , 8 ) ,
        ('apple',      'purple' , 7 ) ,
        ('pear',       'blue'   , 51) ,
        ('chesnut',    'yellow',  0 )   ]


print set( u[1] for u in li ),': all potential colors'
print set( c for f,c,n in li if n!=0),': all effective colors'
print [ c for f,c,n in li if f=='banana' ],': all potential colors of bananas'
print [ c for f,c,n in li if f=='banana' and n!=0],': all effective colors of bananas'
print

print set( u[0] for u in li ),': all potential fruits'
print set( f for f,c,n in li if n!=0),': all effective fruits'
print [ f for f,c,n in li if c=='yellow' ],': all potential fruits being yellow'
print [ f for f,c,n in li if c=='yellow' and n!=0],': all effective fruits being yellow'
print

print len(set( u[1] for u in li )),': number of all potential colors'
print len(set(c for f,c,n in li if n!=0)),': number of all effective colors'
print len( [c for f,c,n in li if f=='strawberry']),': number of potential colors of strawberry'
print len( [c for f,c,n in li if f=='strawberry' and n!=0]),': number of effective colors of strawberry'
print

# sorting li by name of fruit
print sorted(li),'  sorted li by name of fruit'
print

# sorting li by number 
print sorted(li, key = itemgetter(2)),'  sorted li by number'
print

# sorting li first by name of color and secondly by name of fruit
print sorted(li, key = itemgetter(1,0)),'  sorted li first by name of color and secondly by name of fruit'
print

result

set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange', 'silver']) : all potential colors
set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange']) : all effective colors
['blue', 'yellow', 'brown'] : all potential colors of bananas
['blue', 'yellow', 'brown'] : all effective colors of bananas

set(['strawberry', 'chesnut', 'pear', 'banana', 'apple']) : all potential fruits
set(['strawberry', 'pear', 'banana', 'apple']) : all effective fruits
['banana', 'pear', 'strawberry', 'apple', 'chesnut'] : all potential fruits being yellow
['banana', 'pear', 'strawberry', 'apple'] : all effective fruits being yellow

9 : number of all potential colors
8 : number of all effective colors
6 : number of potential colors of strawberry
5 : number of effective colors of strawberry

[('apple', 'blue', 21), ('apple', 'gold', 3), ('apple', 'green', 12), ('apple', 'pink', 9), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'blue', 24), ('banana', 'brown', 14), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'blue', 51), ('pear', 'brown', 5), ('pear', 'gold', 66), ('pear', 'yellow', 10), ('strawberry', 'blue', 16), ('strawberry', 'gold', 0), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('strawberry', 'pink', 8), ('strawberry', 'yellow', 31)]   sorted li by name of fruit

[('apple', 'silver', 0), ('strawberry', 'gold', 0), ('chesnut', 'yellow', 0), ('apple', 'gold', 3), ('strawberry', 'green', 4), ('pear', 'brown', 5), ('apple', 'purple', 7), ('strawberry', 'pink', 8), ('apple', 'pink', 9), ('apple', 'yellow', 9), ('pear', 'yellow', 10), ('apple', 'green', 12), ('banana', 'yellow', 13), ('banana', 'brown', 14), ('strawberry', 'blue', 16), ('apple', 'blue', 21), ('banana', 'blue', 24), ('strawberry', 'orange', 27), ('strawberry', 'yellow', 31), ('pear', 'blue', 51), ('pear', 'gold', 66)]   sorted li by number

[('apple', 'blue', 21), ('banana', 'blue', 24), ('pear', 'blue', 51), ('strawberry', 'blue', 16), ('banana', 'brown', 14), ('pear', 'brown', 5), ('apple', 'gold', 3), ('pear', 'gold', 66), ('strawberry', 'gold', 0), ('apple', 'green', 12), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('apple', 'pink', 9), ('strawberry', 'pink', 8), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'yellow', 10), ('strawberry', 'yellow', 31)]   sorted li first by name of color and secondly by name of fruit

回答 3

在这种情况下,字典可能不是您应该使用的字典。功能更全的库将是更好的选择。可能是真实的数据库。最简单的是sqlite。您可以通过传递字符串’:memory:’而不是文件名来将整个内容保留在内存中。

如果您确实想继续沿着这条路径前进,则可以使用键或值中的额外属性来完成。但是,字典不能是另一本字典的键,而元组可以。该文档说明了允许的内容。它必须是一个不可变的对象,其中包括仅包含字符串和数字的字符串,数字和元组(以及递归仅包含那些类型的更多元组…)。

您可以使用做第一个示例d = {('apple', 'red') : 4},但是要查询所需的内容将非常困难。您需要执行以下操作:

#find all apples
apples = [d[key] for key in d.keys() if key[0] == 'apple']

#find all red items
red = [d[key] for key in d.keys() if key[1] == 'red']

#the red apple
redapples = d[('apple', 'red')]

A dictionary probably isn’t what you should be using in this case. A more full featured library would be a better alternative. Probably a real database. The easiest would be sqlite. You can keep the whole thing in memory by passing in the string ‘:memory:’ instead of a filename.

If you do want to continue down this path, you can do it with the extra attributes in the key or the value. However a dictionary can’t be the key to a another dictionary, but a tuple can. The docs explain what’s allowable. It must be an immutable object, which includes strings, numbers and tuples that contain only strings and numbers (and more tuples containing only those types recursively…).

You could do your first example with d = {('apple', 'red') : 4}, but it’ll be very hard to query for what you want. You’d need to do something like this:

#find all apples
apples = [d[key] for key in d.keys() if key[0] == 'apple']

#find all red items
red = [d[key] for key in d.keys() if key[1] == 'red']

#the red apple
redapples = d[('apple', 'red')]

回答 4

使用键作为元组时,只需使用给定的第二个组件过滤键并对其进行排序:

blue_fruit = sorted([k for k in data.keys() if k[1] == 'blue'])
for k in blue_fruit:
  print k[0], data[k] # prints 'banana 24', etc

排序之所以有效,是因为如果元组的组成部分具有自然顺序,则它们具有自然顺序。

使用键作为完全成熟的对象,只需按即可过滤k.color == 'blue'

您不能真正将dicts用作键,但是可以创建一个最简单的类,例如class Foo(object): pass,并向其动态添加任何属性:

k = Foo()
k.color = 'blue'

这些实例可以用作字典键,但要注意其可变性!

With keys as tuples, you just filter the keys with given second component and sort it:

blue_fruit = sorted([k for k in data.keys() if k[1] == 'blue'])
for k in blue_fruit:
  print k[0], data[k] # prints 'banana 24', etc

Sorting works because tuples have natural ordering if their components have natural ordering.

With keys as rather full-fledged objects, you just filter by k.color == 'blue'.

You can’t really use dicts as keys, but you can create a simplest class like class Foo(object): pass and add any attributes to it on the fly:

k = Foo()
k.color = 'blue'

These instances can serve as dict keys, but beware their mutability!


回答 5

您可能有一个词典,其中的条目是其他词典的列表:

fruit_dict = dict()
fruit_dict['banana'] = [{'yellow': 24}]
fruit_dict['apple'] = [{'red': 12}, {'green': 14}]
print fruit_dict

输出:

{‘香蕉’:[{‘黄色’:24}],’苹果’:[{‘红色’:12},{‘绿色’:14}]}

编辑:正如eumiro指出的那样,您可以使用词典字典:

fruit_dict = dict()
fruit_dict['banana'] = {'yellow': 24}
fruit_dict['apple'] = {'red': 12, 'green': 14}
print fruit_dict

输出:

{‘香蕉’:{‘黄色’:24},’苹果’:{‘绿色’:14,’红色’:12}}

You could have a dictionary where the entries are a list of other dictionaries:

fruit_dict = dict()
fruit_dict['banana'] = [{'yellow': 24}]
fruit_dict['apple'] = [{'red': 12}, {'green': 14}]
print fruit_dict

Output:

{‘banana’: [{‘yellow’: 24}], ‘apple’: [{‘red’: 12}, {‘green’: 14}]}

Edit: As eumiro pointed out, you could use a dictionary of dictionaries:

fruit_dict = dict()
fruit_dict['banana'] = {'yellow': 24}
fruit_dict['apple'] = {'red': 12, 'green': 14}
print fruit_dict

Output:

{‘banana’: {‘yellow’: 24}, ‘apple’: {‘green’: 14, ‘red’: 12}}


回答 6

从类似Trie的数据结构中有效提取此类数据。它还允许快速排序。内存效率可能不会那么好。

传统的trie将单词的每个字母存储为树中的节点。但是在您的情况下,您的“字母”是不同的。您正在存储字符串而不是字符。

它可能看起来像这样:

root:                Root
                     /|\
                    / | \
                   /  |  \     
fruit:       Banana Apple Strawberry
              / |      |     \
             /  |      |      \
color:     Blue Yellow Green  Blue
            /   |       |       \
           /    |       |        \
end:      24   100      12        0

看到这个链接:在Python中的特里

This type of data is efficiently pulled from a Trie-like data structure. It also allows for fast sorting. The memory efficiency might not be that great though.

A traditional trie stores each letter of a word as a node in the tree. But in your case your “alphabet” is different. You are storing strings instead of characters.

it might look something like this:

root:                Root
                     /|\
                    / | \
                   /  |  \     
fruit:       Banana Apple Strawberry
              / |      |     \
             /  |      |      \
color:     Blue Yellow Green  Blue
            /   |       |       \
           /    |       |        \
end:      24   100      12        0

see this link: trie in python


回答 7

您要独立使用两个键,因此有两个选择:

  1. 有两个类型的字典作为存储冗余数据{'banana' : {'blue' : 4, ...}, .... }{'blue': {'banana':4, ...} ...}。然后,搜索和排序很容易,但是您必须确保同时修改字典。

  2. 将其仅存储一个字典,然后编写对其进行迭代的函数,例如:

    d = {'banana' : {'blue' : 4, 'yellow':6}, 'apple':{'red':1} }
    
    blueFruit = [(fruit,d[fruit]['blue']) if d[fruit].has_key('blue') for fruit in d.keys()]

You want to use two keys independently, so you have two choices:

  1. Store the data redundantly with two dicts as {'banana' : {'blue' : 4, ...}, .... } and {'blue': {'banana':4, ...} ...}. Then, searching and sorting is easy but you have to make sure you modify the dicts together.

  2. Store it just one dict, and then write functions that iterate over them eg.:

    d = {'banana' : {'blue' : 4, 'yellow':6}, 'apple':{'red':1} }
    
    blueFruit = [(fruit,d[fruit]['blue']) if d[fruit].has_key('blue') for fruit in d.keys()]
    

‘dict’对象没有属性’has_key’

问题:’dict’对象没有属性’has_key’

在Python中遍历图形时,我收到此错误:

‘dict’对象没有属性’has_key’

这是我的代码:

def find_path(graph, start, end, path=[]):
    path = path + [start]
    if start == end:
        return path
    if not graph.has_key(start):
        return None
    for node in graph[start]:
        if node not in path:
            newpath = find_path(graph, node, end, path)
            if newpath: return newpath
    return None

该代码旨在查找从一个节点到另一节点的路径。代码源:http : //cs.mwsu.edu/~terry/courses/4883/lectures/graphs.html

为什么会出现此错误,我该如何解决?

While traversing a graph in Python, a I’m receiving this error:

‘dict’ object has no attribute ‘has_key’

Here is my code:

def find_path(graph, start, end, path=[]):
    path = path + [start]
    if start == end:
        return path
    if not graph.has_key(start):
        return None
    for node in graph[start]:
        if node not in path:
            newpath = find_path(graph, node, end, path)
            if newpath: return newpath
    return None

The code aims to find the paths from one node to others. Code source: http://cs.mwsu.edu/~terry/courses/4883/lectures/graphs.html

Why am I getting this error and how can I fix it?


回答 0

has_key已在Python 3中删除。从文档中

  • 已删除dict.has_key()–请改用in运算符。

这是一个例子:

if start not in graph:
    return None

has_key was removed in Python 3. From the documentation:

  • Removed dict.has_key() – use the in operator instead.

Here’s an example:

if start not in graph:
    return None

回答 1

has_keyPython 3.0中已被弃用。或者,您可以使用“ in”

graph={'A':['B','C'],
   'B':['C','D']}

print('A' in graph)
>> True

print('E' in graph)
>> False

has_key has been deprecated in Python 3.0. Alternatively you can use ‘in’

graph={'A':['B','C'],
   'B':['C','D']}

print('A' in graph)
>> True

print('E' in graph)
>> False

回答 2

在python3中,has_key(key)被替换为__contains__(key)

在python3.7中测试:

a = {'a':1, 'b':2, 'c':3}
print(a.__contains__('a'))

In python3, has_key(key) is replaced by __contains__(key)

Tested in python3.7:

a = {'a':1, 'b':2, 'c':3}
print(a.__contains__('a'))

回答 3

我认为,仅in在确定某个键是否已存在时才使用它,它被认为是“更多的pythonic” ,如

if start not in graph:
    return None

I think it is considered “more pythonic” to just use in when determining if a key already exists, as in

if start not in graph:
    return None

回答 4

该文档中的整个代码将为:

graph = {'A': ['B', 'C'],
             'B': ['C', 'D'],
             'C': ['D'],
             'D': ['C'],
             'E': ['F'],
             'F': ['C']}
def find_path(graph, start, end, path=[]):
        path = path + [start]
        if start == end:
            return path
        if start not in graph:
            return None
        for node in graph[start]:
            if node not in path:
                newpath = find_path(graph, node, end, path)
                if newpath: return newpath
        return None

写入后,保存文档并按F 5

之后,您将在Python IDLE shell中运行的代码为:

find_path(图,’A’,’D’)

您应该在“ IDLE”中收到的答案是

['A', 'B', 'C', 'D'] 

The whole code in the document will be:

graph = {'A': ['B', 'C'],
             'B': ['C', 'D'],
             'C': ['D'],
             'D': ['C'],
             'E': ['F'],
             'F': ['C']}
def find_path(graph, start, end, path=[]):
        path = path + [start]
        if start == end:
            return path
        if start not in graph:
            return None
        for node in graph[start]:
            if node not in path:
                newpath = find_path(graph, node, end, path)
                if newpath: return newpath
        return None

After writing it, save the document and press F 5

After that, the code you will run in the Python IDLE shell will be:

find_path(graph, ‘A’,’D’)

The answer you should receive in IDLE is

['A', 'B', 'C', 'D'] 

回答 5

尝试:

if start not in graph:

有关更多信息,请参见ProgrammerSought

Try:

if start not in graph:

For more info see ProgrammerSought