遍历两个列表的列表理解无法按预期工作

时间:2019-01-29 12:29:21

标签: python list-comprehension

我想遍历两个列表。第一个列表包含一些浏览器用户代理,第二个列表包含这些浏览器的版本。我只想过滤那些版本大于60的用户代理。

这是我的列表理解的样子:

[link for ver in version for link in useragents if ver > 60]

此列表的问题是它多次打印相同的用户代理。我使用zip函数编写了以下代码,效果很好:

for link, ver in zip(useragents, version):
    if ver > 60:
        # append to list
        print(link)

为什么列表推导会返回意外结果?

5 个答案:

答案 0 :(得分:25)

您的第一个列表理解等同于:

res = []
for ver in version:
    for link in useragents:
        if ver > 60:
            res.append(link)

请注意,您具有时间复杂度为O( n 2 )的嵌套循环,即您要遍历{{1}的每个组合 }和version。假设您的useragentsversion列表对齐,那不是您想要的。

等效于useragents的是以下列表理解:

for

答案 1 :(得分:8)

[link for (link, ver) in zip(useragents, version) if ver > 60]

您仍然必须将两个列表压缩在一起。

答案 2 :(得分:5)

public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
    if (resultCode != RESULT_OK)
        return;
    else {
        Uri treeUri = resultData.getData();
        Log.e("treeuri",treeUri.toString());
        grantUriPermission(getPackageName(), treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        if(Build.VERSION.SDK_INT >= 19)
            getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        String str = treeUri.toString();
        try{
            File dir = new File (Environment.getExternalStorageDirectory().getAbsolutePath());
            if(!dir.exists()){
                dir.mkdir();
            }
            FileOutputStream fos = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath()+"/treeuri.txt", true);
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos));
            writer.write(str);
            writer.flush();
            writer.close();
            fos.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

与zip不同。它不是并行遍历两个序列。它正在迭代这两个序列的所有组合。

就好像你写了:

[link for ver in version for link in useragents if ver > 60]

因此,如果两个序列的长度均为5,则将有25种组合(其中有些被条件for ver in version: for link in useragents: if ver > 60: # append(link) 过滤掉了。)

当您想要并行处理序列时,ver > 60是做到这一点的一种方法,即使是在理解方面也是如此。

zip

答案 3 :(得分:2)

或者,您可以将功能compress()map()结合使用,在其中检查某些条件:

from itertools import compress

filter_ = map(lambda x: x > 60, version)
list(compress(useragents, filter_))

示例:

s = 'ABCDEFG'
nums = range(len(s))

filter_ = map(lambda x: x > 3, nums)
print(list(compress(s, filter_)))
# ['E', 'F', 'G']

答案 4 :(得分:0)

在没有数据的情况下无法确定发生了什么,但是通常,“双重”列表理解与zip不同,而是双重循环,即

[a for b in bs for a in as]

等同于

for b in bs:
    for a in as:
        lst.append(a)