【问题标题】:Shorten loop to list comprehension with multiple for's and ifs/elifs使用多个 for 和 ifs/e ifs 缩短循环以列出理解
【发布时间】:2016-11-06 22:44:48
【问题描述】:

我有这段代码,其中字典键是函数,值是包含关键字的列表。它搜索列出的t 并查看它是否在字典值的列表中。如果是,则运行该值的函数 [key]。如果没有,它将运行NowThis 函数。 count 变量就在那里,所以在这种情况下 t'hello hi'

dct = {doThis:['hi','hello'],
       doThat:['bye','goodbye']}

t = 'hi there' # or 'test'|'goodbye'|'hello hi'
count=0
for listValue in t.split():
    if count > 1 or count < 0:
        break
    elif listValue in [n for v in dct.values() for n in v]:
        for key,vl in dct.iteritems():
            if listValue in vl:
                key()
                count+=1
    elif count==0:
        nowThis()
        count -=1

我确实有这个代码的以前版本,它只是用于 if 和 if,我很容易将其转换为列表理解:

[key() for listValue in t.split() if listValue in [n for v in dct.values() for n in v] for key,vl in dct.iteritems() if listValue in vl]

但是,我无法将当前代码转换为类似列表理解的代码。

【问题讨论】:

  • 您确定要牺牲代码的可读性而不是复杂的列表理解吗?
  • 如果你不使用key的返回值,你不应该创建一个listcomp来执行循环。
  • 我没有仔细查看您的代码,但字典看起来是从后到前的。你为什么不把'hi'、'hello'等字符串作为键,用你的函数作为值?
  • 列表理解不会更快。列表推导的好处在于您可以使用裸表达式,其中map 需要将其包装在用户定义的函数中。比较 [x['foo']['bar] for x in mylist]map(lambda x: x['foo']['bar'], mylist)
  • 另外,您实际上并没有使用 for 循环构建列表,因此列表推导式通过构建列表增加了更多开销。

标签: python list dictionary


【解决方案1】:

正如在 cmets 中所解释的,在这里使用列表推导没有任何好处。它实际上会更慢,因为您将创建一个您实际上并不想要的列表。此外,纯粹出于副作用而使用列表组合被认为是糟糕的设计。

正如我在 cmets 中提到的,你的字典设计是错误的,所以你没有得到使用字典的好处,即 dict 可以快速测试一个键是否存在,它可以快速检索与键关联的值。

假设您当前的代码执行您想要的操作,这里有一个更好的编写方法。

def do_this():
    print 'Do This!\n'

def do_that():
    print 'Do That!\n'

def now_this():
    print 'Now This!\n'

dct = {
    'hi': do_this,
    'hello':  do_this,
    'bye': do_that,
    'goodbye': do_that,
}

data = ('hi there', 'python', 'goodbye hello', '')
for t in data:
    v = t.split(None, 1)[0] if t else ''
    print [t, v]
    dct.get(v, now_this)()

输出

['hi there', 'hi']
Do This!

['python', 'python']
Now This!

['goodbye hello', 'goodbye']
Do That!

['', '']
Now This!

这是一个没有print 语句的for 循环的更紧凑版本:

for t in data:
    dct.get(t.split(None, 1)[0] if t else '', now_this)()

我们使用条件表达式 (t.split(None, 1)[0] if t else ''),因此我们可以处理 t 为空字符串的情况。这是可读性较差的替代版本。 :)

for t in data:
    dct.get((t.split(None, 1) or [''])[0], now_this)()

如果您可以保证 t 永远不会是空字符串,那么您可以使用简单版本:

for t in data:
    dct.get(t.split(None, 1)[0], now_this)()

【讨论】:

    猜你喜欢
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2014-10-27
    相关资源
    最近更新 更多