Python - 使用字典来计算键和值
Python - using dictionary to count keys and values
我是 python 课程的学生,我们创建了一个元组列表(包含 2 个元素),我们试图以各种方式对其进行操作。此外,我们要将这些元组元素转换为字典,并使用字典重新创建操作并避免 for 循环。我坚持的任务是给定一个特定的 id(可以是字典中的键或值)函数 returns 在该字典中找到的所有其他 keys/values。
为此使用字典似乎效率不高,但那是我们在课程中的部分,并且是作业特别要求的。也没有 for 循环(如果可能的话?)。回想一下,id 可以是字典中的键或值。
example_dictionary = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
def get_interactions(example_dictionary, id):
output = ''
for j,k in example_dictionary.items():
if j == id:
output = output + k + ' '
if k == id:
output = output + j + ' '
return output
这段代码工作得很好,但是它 1) 有一个 for 循环(不好)和 2) 不是很 pythonic(有点碍眼)!我怎样才能更有效地使用字典并浓缩我的台词?我在Python3,谢谢!
您可以使用列表理解,尽管有人可能会争辩说它是一种 for 循环:
example_dictionary = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
def get_interactions(dic, id):
output =[v for k, v in dic.items() if k == id] + [k for k,v in dic.items() if v == id]
return output
我不知道如何避免使用 for 循环,除了制作自己的 for 循环,类似于以下内容:
i = 0
def func(tup, id) {
if i < len(dictionary_items):
output = False
if tup[0] == id or tup[1] == id:
output = id + ' '
i += 1
return output
}
dictionary_items = dictionary.items()
func(dictionary_items[0], id)
func(dictionary_items[1], id)
func(dictionary_items[2], id)
等等。但是,那将是丑陋的并且非常非 pythonic。
至于使您的代码更符合 Python 风格,您可以将行 output = output + k + ' '
更改为 output += k + ' '
或 output = k + ' '
(您将字符串 k 和 ' ' 连接到一个空字符串,输出,这对字符串 k 和 ' ').
没有任何改变
此外,您可以检查 if j == id or k == id
而不是两个单独的 if 语句,然后说 output = id + ' '
,因为如果 j 或 k 等于 id,那么 return 无论哪个 j 都没有关系k 等于 id 或者如果你 return id 本身。
您必须检查所有键和值,因此总会出现某种类型的循环。 Python 有很多方法可以在不显式使用 for
.
的情况下迭代(即循环)项目
在没有 for
的情况下迭代项目的一个好方法是使用 filter
, map
, and reduce
内置函数以及用于创建小型匿名函数的 lambda
语法。
from itertools import chain
# Get values for matching keys and vice versa
values = map(lambda x: x[1] if x[0] == id else None, dct.items())
keys = map(lambda x: x[0] if x[1] == id else None, dct.items())
# Then you filter out the None values
# itertools.chain allows us to conveniently do this in one line
matches = filter(lambda x: x is not None, chain(keys, values))
如果您不能使用 itertools.chain
,您只需要一些额外的步骤
keys = filter(lambda x: x is not None, keys)
values = filter(lambda x: x is not None, values)
matches = keys + values
如果您需要 space 分隔的值输出:
output = ' '.join(matches)
预期结果
有一个字典和名为 wanted
的值,您想创建另一个字典作为
原始的删除了所有不具有键或值等于 wanted
值的项目。
可以用pytest测试用例的形式表达,有几个场景。
import pytest
scenarios = [
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"A",
# expected (result)
{'A': 'C', 'D': 'A'},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"E",
# expected (result)
{'R': 'E'},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"D",
# expected (result)
{'D': 'A', 'C': 'D'},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"nothere",
# expected (result)
{},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"A",
# expected (result)
{'A': 'C', 'D': 'A'},
],
]
# replace with real implementation
def get_key_or_val_itms(dct, wanted):
# something comes here
return result
@pytest.mark.parametrize("scenario", scenarios)
def test_it(scenario):
dct, wanted, expected = scenario
assert get_key_or_val_itms(dct, wanted) == expected
除了 scenarios
之外,不要理会任何事情。它列出了几个带有输入的测试场景
字典、wanted
的值和预期结果。
解决方案的基石
dict.items() - 字典到元组列表
>>> dct = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
>>> dct.items()
[('A', 'C'), ('R', 'E'), ('D', 'A'), ('L', 'R'), ('C', 'D')]
测试 tuple/list
中某个值的成员资格
>>> 'A' in ('A', 'C')
True
>>> 'A' in ('R', 'E')
False
Lambda 函数测试,如果 wanted
出现在元组中
lambda
允许 "in place" 函数定义。它经常被用在一些地方,
其中一些函数需要引用一个函数。
首先,创建命名函数tuple_wanted
>>> wanted = "A"
>>> def tuple_wanted(tpl):
... return wanted in tpl
并测试它(注意,wanted
现在的值为 "A"):
>>> tuple_wanted(('A', 'C'))
True
>>> tuple_wanted(('R', 'E'))
False
现在创建函数。为了使用它,我们将 lambda
的结果存储在 fun
:
中
>>> fun = lambda tpl: wanted in tpl
可以像tuple_wanted
之前一样使用:
>>> fun(('A', 'C'))
True
>>> fun(('R', 'E'))
False
后面我们会直接使用lambda
的结果(见filter
)
将其存储到任何变量中。
filter
删除所有未通过某些测试的列表项
filter
获取测试函数和可迭代对象(例如项目列表)以通过它进行测试。
调用 filter
的结果是 iterable 中的项目列表,它通过了测试。
在我们的例子中,我们只想传递包含 wanted
值(例如 "A")
的元组
>>> filter(tuple_wanted, dct.items())
[('A', 'C'), ('D', 'A')]
>>> filter(fun, dct.items())
[('A', 'C'), ('D', 'A')]
>>> filter(lambda tpl: wanted in tpl, dct.items())
[('A', 'C'), ('D', 'A')]
将包含 2 个项目的元组列表转换为字典
>>> tpllst = [('A', 'C'), ('D', 'A')]
>>> dict(tpllst)
{'A': 'C', 'D': 'A'}
执行工作的函数
长版
这个版本来一步步解释是怎么回事:
def get_key_or_val_itms(dct, wanted):
# dict as [(key, val), (key2, val2), ...]
tpldct = dct.items()
# find tuples, where either key or val equals `wanted` value
# first make function, which detects, the tuple we search for
def tuple_wanted(tpl):
return wanted in tpl
# now use it to filter only what we search for
restpldct = filter(tuple_wanted, tpldct)
# finally, turn the result into dict
return dict(restpldct)
简短版
def get_key_or_val_itms(dct, wanted):
return dict(filter(lambda tpl: wanted in tpl, dct.items()))
结论
有效(无论是长版本还是短版本的函数):
>>> dct = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
>>> wanted = "A"
>>> get_key_or_val_itms(dct, wanted)
{'A': 'C', 'D': 'A'}
如果将函数放入测试套件的文件中,调用$ py.test -sv the_file.py
将输出:
$ py.test -sv the_file.py
py.test================================ test session starts =========================
=======
platform linux2 -- Python 2.7.9, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- /home/javl/
.virtualenvs/stack/bin/python2
cachedir: .cache
rootdir: /home/javl/sandbox/stack/dict, inifile:
collected 5 items
countdict.py::test_it[scenario0] PASSED
countdict.py::test_it[scenario1] PASSED
countdict.py::test_it[scenario2] PASSED
countdict.py::test_it[scenario3] PASSED
countdict.py::test_it[scenario4] PASSED
============================= 5 passed in 0.01 seconds ==============================
可以看出,所有场景都在通过。
解释 py.test
的工作原理超出了本答案的范围,要了解更多信息,请参阅 http://pytest.org/latest/
我是 python 课程的学生,我们创建了一个元组列表(包含 2 个元素),我们试图以各种方式对其进行操作。此外,我们要将这些元组元素转换为字典,并使用字典重新创建操作并避免 for 循环。我坚持的任务是给定一个特定的 id(可以是字典中的键或值)函数 returns 在该字典中找到的所有其他 keys/values。
为此使用字典似乎效率不高,但那是我们在课程中的部分,并且是作业特别要求的。也没有 for 循环(如果可能的话?)。回想一下,id 可以是字典中的键或值。
example_dictionary = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
def get_interactions(example_dictionary, id):
output = ''
for j,k in example_dictionary.items():
if j == id:
output = output + k + ' '
if k == id:
output = output + j + ' '
return output
这段代码工作得很好,但是它 1) 有一个 for 循环(不好)和 2) 不是很 pythonic(有点碍眼)!我怎样才能更有效地使用字典并浓缩我的台词?我在Python3,谢谢!
您可以使用列表理解,尽管有人可能会争辩说它是一种 for 循环:
example_dictionary = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
def get_interactions(dic, id):
output =[v for k, v in dic.items() if k == id] + [k for k,v in dic.items() if v == id]
return output
我不知道如何避免使用 for 循环,除了制作自己的 for 循环,类似于以下内容:
i = 0
def func(tup, id) {
if i < len(dictionary_items):
output = False
if tup[0] == id or tup[1] == id:
output = id + ' '
i += 1
return output
}
dictionary_items = dictionary.items()
func(dictionary_items[0], id)
func(dictionary_items[1], id)
func(dictionary_items[2], id)
等等。但是,那将是丑陋的并且非常非 pythonic。
至于使您的代码更符合 Python 风格,您可以将行 output = output + k + ' '
更改为 output += k + ' '
或 output = k + ' '
(您将字符串 k 和 ' ' 连接到一个空字符串,输出,这对字符串 k 和 ' ').
没有任何改变
此外,您可以检查 if j == id or k == id
而不是两个单独的 if 语句,然后说 output = id + ' '
,因为如果 j 或 k 等于 id,那么 return 无论哪个 j 都没有关系k 等于 id 或者如果你 return id 本身。
您必须检查所有键和值,因此总会出现某种类型的循环。 Python 有很多方法可以在不显式使用 for
.
在没有 for
的情况下迭代项目的一个好方法是使用 filter
, map
, and reduce
内置函数以及用于创建小型匿名函数的 lambda
语法。
from itertools import chain
# Get values for matching keys and vice versa
values = map(lambda x: x[1] if x[0] == id else None, dct.items())
keys = map(lambda x: x[0] if x[1] == id else None, dct.items())
# Then you filter out the None values
# itertools.chain allows us to conveniently do this in one line
matches = filter(lambda x: x is not None, chain(keys, values))
如果您不能使用 itertools.chain
,您只需要一些额外的步骤
keys = filter(lambda x: x is not None, keys)
values = filter(lambda x: x is not None, values)
matches = keys + values
如果您需要 space 分隔的值输出:
output = ' '.join(matches)
预期结果
有一个字典和名为 wanted
的值,您想创建另一个字典作为
原始的删除了所有不具有键或值等于 wanted
值的项目。
可以用pytest测试用例的形式表达,有几个场景。
import pytest
scenarios = [
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"A",
# expected (result)
{'A': 'C', 'D': 'A'},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"E",
# expected (result)
{'R': 'E'},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"D",
# expected (result)
{'D': 'A', 'C': 'D'},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"nothere",
# expected (result)
{},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"A",
# expected (result)
{'A': 'C', 'D': 'A'},
],
]
# replace with real implementation
def get_key_or_val_itms(dct, wanted):
# something comes here
return result
@pytest.mark.parametrize("scenario", scenarios)
def test_it(scenario):
dct, wanted, expected = scenario
assert get_key_or_val_itms(dct, wanted) == expected
除了 scenarios
之外,不要理会任何事情。它列出了几个带有输入的测试场景
字典、wanted
的值和预期结果。
解决方案的基石
dict.items() - 字典到元组列表
>>> dct = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
>>> dct.items()
[('A', 'C'), ('R', 'E'), ('D', 'A'), ('L', 'R'), ('C', 'D')]
测试 tuple/list
中某个值的成员资格>>> 'A' in ('A', 'C')
True
>>> 'A' in ('R', 'E')
False
Lambda 函数测试,如果 wanted
出现在元组中
lambda
允许 "in place" 函数定义。它经常被用在一些地方,
其中一些函数需要引用一个函数。
首先,创建命名函数tuple_wanted
>>> wanted = "A"
>>> def tuple_wanted(tpl):
... return wanted in tpl
并测试它(注意,wanted
现在的值为 "A"):
>>> tuple_wanted(('A', 'C'))
True
>>> tuple_wanted(('R', 'E'))
False
现在创建函数。为了使用它,我们将 lambda
的结果存储在 fun
:
>>> fun = lambda tpl: wanted in tpl
可以像tuple_wanted
之前一样使用:
>>> fun(('A', 'C'))
True
>>> fun(('R', 'E'))
False
后面我们会直接使用lambda
的结果(见filter
)
将其存储到任何变量中。
filter
删除所有未通过某些测试的列表项
filter
获取测试函数和可迭代对象(例如项目列表)以通过它进行测试。
调用 filter
的结果是 iterable 中的项目列表,它通过了测试。
在我们的例子中,我们只想传递包含 wanted
值(例如 "A")
>>> filter(tuple_wanted, dct.items())
[('A', 'C'), ('D', 'A')]
>>> filter(fun, dct.items())
[('A', 'C'), ('D', 'A')]
>>> filter(lambda tpl: wanted in tpl, dct.items())
[('A', 'C'), ('D', 'A')]
将包含 2 个项目的元组列表转换为字典
>>> tpllst = [('A', 'C'), ('D', 'A')]
>>> dict(tpllst)
{'A': 'C', 'D': 'A'}
执行工作的函数
长版
这个版本来一步步解释是怎么回事:
def get_key_or_val_itms(dct, wanted):
# dict as [(key, val), (key2, val2), ...]
tpldct = dct.items()
# find tuples, where either key or val equals `wanted` value
# first make function, which detects, the tuple we search for
def tuple_wanted(tpl):
return wanted in tpl
# now use it to filter only what we search for
restpldct = filter(tuple_wanted, tpldct)
# finally, turn the result into dict
return dict(restpldct)
简短版
def get_key_or_val_itms(dct, wanted):
return dict(filter(lambda tpl: wanted in tpl, dct.items()))
结论
有效(无论是长版本还是短版本的函数):
>>> dct = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
>>> wanted = "A"
>>> get_key_or_val_itms(dct, wanted)
{'A': 'C', 'D': 'A'}
如果将函数放入测试套件的文件中,调用$ py.test -sv the_file.py
将输出:
$ py.test -sv the_file.py
py.test================================ test session starts =========================
=======
platform linux2 -- Python 2.7.9, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- /home/javl/
.virtualenvs/stack/bin/python2
cachedir: .cache
rootdir: /home/javl/sandbox/stack/dict, inifile:
collected 5 items
countdict.py::test_it[scenario0] PASSED
countdict.py::test_it[scenario1] PASSED
countdict.py::test_it[scenario2] PASSED
countdict.py::test_it[scenario3] PASSED
countdict.py::test_it[scenario4] PASSED
============================= 5 passed in 0.01 seconds ==============================
可以看出,所有场景都在通过。
解释 py.test
的工作原理超出了本答案的范围,要了解更多信息,请参阅 http://pytest.org/latest/