我是python课程的学生,我们创建了一个元组列表(包含2个元素),我们试图以各种方式操作它们。此外,我们将这些元组元素转换为字典,并使用字典重新创建操作并避免循环。我坚持的任务是,给定一个特定的id(可能是字典中的一个键OR值),该函数返回在该字典中找到的所有其他键/值。
为此使用字典似乎并不高效,但这是我们在课程中所处的部分,并且具体由作业提出。对于循环也没有(如果可能的话?)。回想一下,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(有点像眼睛)!我怎样才能更有效地使用字典并压缩我的字符串呢?我在Python 3中,谢谢!
答案 0 :(得分:0)
你可以使用列表推导,虽然有人可能会认为它是一种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
答案 1 :(得分:0)
我不知道如何避免使用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。
至于使代码更加pythonic,您可以将行output = output + k + ' '
更改为output += k + ' '
或output = k + ' '
(您可以将字符串k和&#39;&#39连接起来;输出一个空字符串,它不会改变字符串k和&#39;)
此外,你可以检查if j == id or k == id
而不是两个单独的if语句,然后说output = id + ' '
,因为如果j或k等于id,如果你返回j和k中的任何一个并不重要等于id或者如果你返回id本身。
答案 2 :(得分:0)
您必须检查所有键和值,因此总会出现某种类型的循环。 Python有许多方法可以在没有明确使用for
的情况下迭代(即循环)项目。
在没有for
的情况下迭代项目的一种好方法是使用filter
,map
和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
如果您需要以空格分隔的值输出:
output = ' '.join(matches)
答案 3 :(得分:0)
有一个字典和名为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
的值和预期结果。
>>> dct = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
>>> dct.items()
[('A', 'C'), ('R', 'E'), ('D', 'A'), ('L', 'R'), ('C', 'D')]
>>> 'A' in ('A', 'C')
True
>>> 'A' in ('R', 'E')
False
wanted
lambda
允许“就地”功能定义。它经常用在地方,
其中一些函数需要引用函数。
首先,创建命名函数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')]
>>> 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/