简体   繁体   English

列表理解嵌套在字典理解中

[英]List Comprehension nested in Dict Comprehension

I want to create a dict with lists as values, where the content on the lists depends on whether or not the key (numbers 1 to 100) is dividable by 3,5 and/or 7我想创建一个以列表作为值的字典,其中列表中的内容取决于键(数字 1 到 100)是否可以被 3,5 和/或 7 整除

The output would be like this: output 将是这样的:

{
    1: ['nodiv3', 'nodiv5', 'nodiv7'],
    3: ['div3', 'nodiv5', 'nodiv7'],
    15: ['div3', 'div5', 'nodiv7'],
}

Similar questions where about filtering the list/values, not creating them.关于过滤列表/值而不是创建它们的类似问题。

dict_divider = {}
for x in range(0,101):
    div_list= []
    if x % 3 == 0:
        div_list.append('div3')
    else:
        div_list.append('nodiv3')
    if x % 5 == 0:
        div_list.append('div5')
    else:
        div_list.append('nodiv5')
    if x % 7 == 0:
        div_list.append('div7')
    else:
        div_list.append('nodiv7')
    dict_divider[x] = div_list

This works just fine, but is there a way to do this with a pythonic one-/twoliner?这工作得很好,但是有没有办法用 pythonic one-/twoliner 来做到这一点?

Something along like this: d = dict((val, range(int(val), int(val) + 2)) for val in ['1', '2', '3'])像这样: d = dict((val, range(int(val), int(val) + 2)) for val in ['1', '2', '3'])

Pythonic is not about one or two liners. Pythonic 不是关于一个或两个衬里的。 In my opinion is (mainly) about readability, perhaps this could be considered more pythonic :在我看来(主要)是关于可读性,也许这可以被认为是更pythonic的:

def label(n, divisor):
    return f"{'' if n % divisor == 0 else 'no'}div{divisor}"


def find_divisors(n, divisors=[3, 5, 7]):
    return [label(n, divisor) for divisor in divisors]


dict_divider = {x: find_divisors(x) for x in range(1, 101)}

print(dict_divider) 

You don't actually need to do all these brute-force divisions.您实际上不需要执行所有这些蛮力除法。 Every third number is divisible by three, every seventh number is divisible by seven, etc:每第三个数可被三整除,每第七个数可被七整除,依此类推:

0 1 2 3 4 5 6 7 8 9 ...  <-- range(10)
0 1 2 0 1 2 0 1 2 0 ...  <-- mod 3

0 1 2 3 4 5 6 7 8 9 ...  <-- range(10)
0 1 2 3 4 5 6 0 1 2 ...  <-- mod 7

So the best approach should take advantage of that fact, using the repeating patterns of modulo.所以最好的方法应该利用这个事实,使用模的重复模式。 Then, we can just zip the range with however many iterators you want to use.然后,我们可以只使用 zip 这个范围,无论你想使用多少迭代器。

import itertools

def divs(n):
    L = [f"div{n}"] + [f"nodiv{n}"] * (n - 1)
    return itertools.cycle(L)

repeaters = [divs(n) for n in (3, 5, 7)]
d = {x: s for x, *s in zip(range(101), *repeaters)}

you could write a second loop so that you only have to write if...else only once你可以写第二个循环,这样你只需要写if...else一次

dict_divider = {}
div_check_lst = [3, 5, 7]
for x in range(0,101):
    div_list= []
    for div_check in div_check_lst:
        if x % div_check == 0:
            div_list.append(f'div{str(div_check)}')
        else:
            div_list.append(f'nodiv{str(div_check)}')
    dict_divider[x] = div_list

or要么

dict_divider = {x:[f'{'no' * x % div_check != 0}div{str(div_check)}' for x in range(0,101) for div_check in div_check_lst]}

There is actually a one liner that isnt even that complicated:)实际上有一个甚至没有那么复杂的衬垫:)

my_dict = {}
for i in range(100):
    my_dict[i] = ['div' + str(n) if i % n == 0 else 'nodiv' + str(n) for n in [3,5,7]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM