Python具有多个Iterables的所有功能

时间:2014-03-20 19:59:15

标签: python

我有一个文件列表,如果列表中没有给定的文件名,则需要设置一个标志。所以我有:

if all('FileName' not in f for f in files):
    # set flag

我想扩展此检查以查找多个文件名,因此我创建了一个文件名列表:

file_names = ['FileName', 'FileName2']

在psuedo代码中,我正在寻找:

if all(#all file names in files_names# not in f for f in files):
    # set flag

我还能以某种方式使用内置的所有功能来实现这一点吗?或者我需要将它分成多个语句吗?

感谢您的帮助。

3 个答案:

答案 0 :(得分:5)

如果我理解正确的话......一种方法是将两者都转换成集:

files = set(files)
file_names = set(file_names)

if not file_names <= files:
    # set flag

请注意,<=是子集运算符(.issubset的快捷方式)。

编辑如果要检查所有文件是否都在files中,那么您可以使用交叉点运算符&(或.intersection方法)来检查两组中是否有共同元素:

if not file_names & files:
    # set flag

如果要保留列表结构,则可以使用临时转换:

if not set(file_names) & set(files):
    # set flag
# file_names is still a list

该解决方案不仅优雅而且高效。在这里阅读更多关于集合的内容:

http://docs.python.org/2/library/sets.html

编辑2 如果您想检查file_names中的名称是否包含 <(与我的解决方案不同,我只检查名称之间的严格相等)在files的名称中,您可以使用此:

if all(all(name not in fn for fn in files) for name in file_names):
    # set flag

与您编写的伪代码非常相似。它展示了Python的美妙之处。 :D在这种情况下,使用集合并不重要。

答案 1 :(得分:0)

如果您想继续以列表形式对它们进行操作,您实际上可以避免将它们作为集合单独投射,例如:

if not set(file_names).issubset(files):
    # set flag

type(file_names)

仍会返回:

<type 'list'>

答案 2 :(得分:0)

似乎您第一次使用all()是不必要的,因为看起来您只需要:

if 'FileName' not in files:
#set flag

然而,您提出的新问题可能会受益于all()或取决于您希望实现的目标(all()的输出可能有点欺骗)您也可以使用any()根据{{​​3}} all()实际

  

如果迭代的所有元素都为真(或者如果是),则返回[s]为真   iterable是空的)

这意味着如果你有一个&#39;文件名&#39;并且您正在检查以下方案存在的files列表

# all file names present in files
file_names = ['file','file1','file2']
files # with files ['file','file1','file2','filen']
not all(f in files for f in file_names) #False

# no file names to be compared against
file_names = []
files # with files ['file','file1','file2','filen']
not all(f in files for f in file_names) # True

# some file names not present in files
file_names = ['file','foo','bar','baz']
files # with files ['file','file1','file2','filen']
not all(f in files for f in file_names) # True

您会注意到最后两个是相同的,在这些含糊不清的情况下,我更喜欢使用any() documentation

  

如果iterable的任何元素为true,则返回True。如果iterable为空,则返回False。

这样

# all file names present in files
file_names = ['file','file1','file2']
files # with files ['file','file1','file2','filen']
any(f not in files for f in file_names) # False

# no file names to be compared against
file_names = []
files # with files ['file','file1','file2','filen']
any(f not in files for f in file_names) # False

# some file names not present in files
file_names = ['file','foo','bar','baz']
files # with files ['file','file1','file2','filen']
any(f not in files for f in file_names) # True

这意味着您不必执行任何其他逻辑来确定files是否为空。但是,这是一个边缘情况,您似乎可以控制files包含的内容,因此any()all()就足够了。

在扩展的情况下,你要检查你的file_name是否包含在列表中文件的名称中(这很有趣),然后作为#freakish声明你可以嵌套{{ 1}}或any()语句

all()

虽然这适用于您的情况,但我认为更有用且更性感的中途documented倒置版本

all(all(name not in fn for fn in files) for name in file_names):
# set flag

为什么它更实用?因为简单地取出all(not any(name in file for file in files) for name in file_names) 现在允许另一个有用的问题:我看到的任何文件是否存在?