2

我是 Python 的初学者,在匹配两个包含字符串的列表时遇到了问题,

我使用正则表达式从 txt Metafile 中提取了 Landsat 图像的波段名称,并有一个这样的列表;

bant = ['LT5YYYYYYYYYYYYYXXX02_B1.TIF', 'LT5YYYYYYYYYYYYYXXX02_B2.TIF','LT5YYYYYYYYYYYYYXXX02_B3.TIF', 'LT5YYYYYYYYYYYYYXXX02_B4.TIF', 'LT5YYYYYYYYYYYYYXXX02_B5.TIF', 'LT5YYYYYYYYYYYYYXXX02_B6.TIF', 'LT5YYYYYYYYYYYYYXXX02_B7.TIF']

“YYYYYYYYYYYYYY”是随场景变化的乐队特定名称。我将每个字符串分配给一个变量,然后分配给一个新列表。

        bant1 = bant[0]
        bant2 = bant[1]
               .
               .
        bant7 = bant[6]
        bant = [bant1,bant2,bant3,bant4,bant5,bant6,bant7]

此外,通过使用 Python os 模块,我提取了与 txt Metafile 位于同一目录中的 GeoTIFF 文件的名称,如下所示;

import os
import re
def mtl():
file=[]
path = os.getcwd()
for filelist in os.listdir(path):
    if filelist.endswith(".TIF"):
        file.append(filelist)

输出:

file = ['LT5YYYYYYYYYYYYYXXX02_B1.TIF', 'LT5YYYYYYYYYYYYYXXX02_B2.TIF']

所以我遇到的问题是如何比较这两个列表,“bant”和“file”。并打印在列表中找到的波段是 bant1、bant2。文件列表中的字符串数量是可变的(可能某些文件被用户删除,因此不包含在文件列表中)。

对不起我的英语不好。感谢您的帮助

4

2 回答 2

5

您在寻找固定的交叉点吗?

In [16]: bant = ['LT5YYYYYYYYYYYYYXXX02_B1.TIF', 'LT5YYYYYYYYYYYYYXXX02_B2.TIF','LT5YYYYYYYYYYYYYXXX02_B3.TIF', 'LT5YYYYYYYYYYYYYXXX02_B4.TIF', 'LT5YYYYYYYYYYYYYXXX02_B5.TIF', 'LT5YYYYYYYYYYYYYXXX02_B6.TIF', 'LT5YYYYYYYYYYYYYXXX02_B7.TIF']

In [17]: file = ['LT5YYYYYYYYYYYYYXXX02_B1.TIF', 'LT5YYYYYYYYYYYYYXXX02_B2.TIF']

In [18]: set(bant).intersection(file)
Out[18]: set(['LT5YYYYYYYYYYYYYXXX02_B1.TIF', 'LT5YYYYYYYYYYYYYXXX02_B2.TIF'])

注意sets 是无序的,所以返回的结果可能与orset(bant).intersection(file)给出的顺序不对应。如果您需要保留 的顺序,那么您可以使用bantfilebant

fileset = set(file)
[b for b in bant if b in fileset]

此外,您的定义方法file可以简化为:

import glob
files = glob.glob('*.TIF')

可以打印

通过使用 bant = [bant1,bant2,bant3,bant4,bant5,bant6,bant7] 列表找到(或匹配)的波段是 bant1, bant2"。

但在我们这样做之前,我可以尝试劝阻您不要命名bant: bant1bant2等中的项目吗?

你说项目的数量在bant运行之前是未知的,那么你是如何为每个项目赋予自己的变量名的呢?这是可以做到的,但不是必须的。改用 Python 索引:bant[0]代替bant1bant[1]代替bant2等。通过这样做,您将能够比尝试为每个项目提供编号变量名称bant更容易地进行编程。bant

于 2013-01-04T19:39:56.517 回答
2

附带说明,不要命名变量file——它是内置类型的名称(在 Python 2.x 中),因此使用它会导致混淆。此外,拥有一个文件名列表并调用它file而不是filenames.

天真的方法是使用嵌套for循环:

print('The bands found (or matches) are', end=' ')
for band in bant:
    for filename in filenames:
        if band == filename:
            print(band + ',', end=' ')
            break
print()

但是您可以使用in运算符来简化此操作:

print('The bands found (or matches) are', end=' ')
for band in bant:
    if band in filenames:
        print(band + ',', end=' ')
print()

如果您使用的是 Python 2.x 而不是 3.x,则需要稍作更改:

print 'The bands found (or matches) are',
for band in bant:
    if band in filenames:
        print band + ',',
print

如果要打印索引而不是每个匹配波段的值,可以使用enumerate让您同时迭代索引和波段,如下所示:

print('The bands found (or matches) are', end=' ')
for i, band in enumerate(bant):
    if band in filenames:
        print('bant{},'.format(i), end=' ')
print()

无论如何,您可能会注意到这,在最后留下了额外的内容。为了解决这个问题,您需要跟踪您是否已经打印了任何波段,并,在除第一个之外的每个波段之前打印一个。那会很快变得丑陋。

为了解决这个问题,您通常希望建立一个匹配集合,然后您可以使用join. 像这样:

matches = []
for i, band in enumerate(bant):
    if band in filenames:
        matches.append('bant{}'.format(i))
print('The bands found (or matches) are', ', '.join(matches))

干净多了。但是您可以通过使用列表推导来使这更简单:

matches = ['bant{}'.format(i) for i, band in enumerate(bant) if band in filenames] 
print('The bands found (or matches) are', ', '.join(matches))

如果您阅读了理解和等效列表,您应该能够看到它们是如何做同样的事情的,但无需显式创建列表并append一遍又一遍地调用它。

现在,如果您考虑一下,您可能会注意到您正在对整个列表进行filenames一次线性搜索band。当只有 8 个波段和 6 个文件名时,这并不重要,因为最坏的情况是 48 个比较,但如果每个都有 1000 个呢?1000000 次比较将花费更长的时间。

如果你filenames变成 a set,每个band in filenames只进行 1 次比较,而不是 N 次比较,所以如果每个有 1000 次,你将只进行 1000 次比较而不是 1000000 次。所以:

filenameset = set(filename)
matches = ['bant{}.format(i) for i, band in enumerate(bant) if band in filenameset]
print('The bands found (or matches) are', ', '.join(matches))

您可以进行进一步的改进,但只要您了解为什么会这样,您就完成了。

于 2013-01-04T19:52:41.590 回答