如何将一个数组中的一个元素以数字方式与python中另一个数组中的另一个元素进行比较

时间:2012-06-20 13:36:22

标签: python

我是python的新手,为两个制表符分隔的输入文件制作了两个数组。我正在寻找一种方法来将一个数组的列(元素)以数字方式与另一个数组的元素进行比较。有没有办法做到这一点。我的代码到现在为止

#!/usr/bin/python
import sys
from array import *
#print len(sys.argv)
if len(sys.argv) != 4:
 print 'Usage: python scores.py <infile1> <infile2> <outfile>'
 sys.exit(1)

f1 = open ("12877overlappedallvariants.gvf", "r")
f2 = open ("unmatched.12877overlappedallvariants.gvf", "r")
f3 = open ("out.txt", "w")

for line in f1.readlines():
 cols = line.split('\t')
 #print cols[5:6]


for line in f2.readlines():
 cols1 = line.split('\t')
 #print cols1[5:6]

我在下面的代码部分尝试了这个但不起作用

slice1 = cols[5:6]
slice2 = cols1[5:6]
new_list = []
for element in slice1:
 if element in slice2:
  new_list.append(element)
  print new_list  

我试图看看array1的元素5是否等于,大于或小于array2的元素5。任何帮助表示赞赏。感谢。

3 个答案:

答案 0 :(得分:1)

值得注意的是,这些是列表,而不是数组。有区别。

每次循环时你都会覆盖cols - 这意味着你只能得到最后一行数据 - 这里有一个列表理解来获取你想要的所有数据,或者更好的是,根本就没有完全存储数据 - 按照你想要的操作进行操作。

比较的主要问题是你正在采用列表切片,而不是仅仅采用你需要的元素。这使你想要做的事情过于复杂。

因此,正如我在评论中提到的,您可以对初始代码进行大量改进 - 主要是with语句和csv模块。

首先,使用with语句打开文件。我们也使用csv.reader(),使用"excel-tab"方言,因为它是制表符分隔文件,csv.QUOTE_NONNUMERIC告诉它值是数字,所以我们不必将它们从字符串以后。请注意,如果只有某些值是数字,则需要引用所有非数字值才能使用此方法,或者明确转换这些值而不使用它。

with open("file1.tsv") as file1, open("file2.tsv") as file2:
    rows = csv.reader(file2, dialect="excel-tab", quoting=csv.QUOTE_NONNUMERIC)
    rows1 = csv.reader(file2, dialect="excel-tab", quoting=csv.QUOTE_NONNUMERIC)

要执行检查,只需执行以下操作(从上面with块中继续):

    for cols, cols1 in zip(rows, rows1): #Use itertools.izip() in 2.x for efficiency.
        first = cols[4]
        second = cols1[4]

        if first < second:
            ...
        elif first == second:
            ...
        else: #first > second
            ...

请注意使用zip一次循环遍历这两个文件。我们需要循环遍历文件,因为它们一次返回一行,每行都是每列的数据列表。然后,您可以随意使用数据。我给出了一个比较第五个值的例子(注意索引4 - python是0索引的 - 也就是说,第一个值是0,所以第五个值是{{1} })。

通过循环浏览文件,我们确保不必创建列表并临时存储数据 - 如果我们最终处理大文件,这将非常有用。

如果您需要稍后使用该数据,并希望将其作为列表,则可以通过在{{1}周围调用4来简单地创建两个rows对象列表}第

答案 1 :(得分:0)

有一些事情你需要注意 - 首先,在阅读你的文件之后,你只存储了最后一行(在一个名为'cols'的变量中不少;)。循环如:

lines1=f1.readlines()
lines2=f2.readlines()

for f1line,f2line in zip(lines1,lines2):
    #compare here

可能更合适。这会将两个文件的全部内容读入内存 - 有一些方法可以在不读取大量数据的情况下执行此操作,但有时这是最简单的方法。 zip可能有点令人困惑,但基本上,它匹配file1的第一行和file2的第一行,然后匹配两个文件的第二行,依此类推......

如@Lattyware的评论所述,上述内容相当于:

for f1line,f2line in zip(f1,f2):
    #compare here

因为文件可以迭代。在python 2中,它仍将一次读取/存储两个文件,但在python 3中,它一次只能从每个文件中生成一行。最后,如果您不想在python 2中存储文件的所有内容,可以使用itertools.izip

import itertools
for f1line,f2line in itertools.izip(f1,f2):
    #compare here    

的工作原理与zip类似,只是它一次产生一个元素。这里的缺点是当你转移到python 3时itertools.izip消失了......但是,在这种情况下,2to3应该进行适当的转换。 (有关详细信息,请参阅评论)。

至于比较,这在很大程度上取决于文件包含的内容。如果它包含数字,你可以这样做......

 for f1line,f2line in zip(lines1,lines2):
     row1=map(float,f1line.split())
     row2=map(float,f2line.split())
     #compare the 5th element
     if(row1[4]==row2[4]):
         #equal
     elif(row1[4]>row2[4]):
         ... 

如果你没有map(float,...)位,python将进行字符串比较。

如果你想现在进行比较并稍后使用比较结果,那么

python也有cmp function可能很有用。

答案 2 :(得分:0)

我会这样写:

import csv

file1 = csv.reader(open('name1'), delimiter='\t')
file2 = csv.reader(open('name2'), delimiter='\t')

for row1, row2 in zip(file1, file2):
    print cmp(row1[5], row2[5])

`

cmp返回-1表示lt,0表示eq,或1表示gt

如果行?[5]是数字,那么......

print cmp(float(row1[5]), float(row2[5])) # or int, or any other dtype