在文件中找到最小的浮点数然后打印它并在其上方排列

时间:2013-07-07 21:38:10

标签: python python-2.7 min

我的数据文件如下所示:

3.6-band 
6238
Over
0.5678
Over
0.6874
Over
0.7680
Over
0.7834

我想要做的是挑选最小的浮点数和它正上方的单词并打印这两个值。我不知道我在做什么。我试过了

df=open('filepath')
  for line in df:
    df1=line.split()
    df2=min(df1)

这是我尝试至少尝试隔离最小浮子的尝试。问题是它只是给了我最后一个值。我认为这是一个python的问题,不知道重复迭代,但再次......不知道我在做什么。我尝试了df2=min(df1.seek(0))但没有成功,收到错误说no attribute seek。所以这就是我到目前为止所尝试的,我仍然不知道如何打印最小浮动之前的行。建议/帮助/建议将不胜感激,谢谢。

作为旁注:这个数据文件是一个具有相似特征的较大的文件的例子,但是“Over”这个词也可能是“Under”,这就是我需要打印它的原因。

5 个答案:

答案 0 :(得分:2)

将项目存储在列表[word,num]对列表中,然后在列表列表中应用min。使用key min参数指定必须使用哪个项目来比较项目。:

with open('abc') as f:
    lis = [[line.strip(),next(f).strip()] for line in f]
    minn = min(lis, key = lambda x: float(x[1]))
    print "\n".join(minn)
...     
Over
0.5678

此处lis如下所示:

[['3.6-band', '6238'], ['Over', '0.5678'], ['Over', '0.6874'], ['Over', '0.7680'], ['Over', '0.7834']]

答案 1 :(得分:2)

您可以使用grouper recipeizip(*[iterator]*2)df中的行聚为2组。然后,要找到最小的行,使用min and its key parameter指定用于比较的代理。在这种情况下,对于每对行(p, l),我们希望使用第二行的浮点float(l)作为代理:

import itertools as IT
with open('filepath') as df:
    previous, minline = min(IT.izip(*[df]*2), 
                            key=lambda (p, l): float(l))
    minline = float(minline)
    print(previous)
    print(minline)

打印

Over

0.5678

石斑鱼食谱的解释:

要了解石斑鱼食谱,首先要看一下如果df是一个列表会发生什么:

In [1]: df = [1, 2]

In [2]: [df]*2
Out[2]: [[1, 2], [1, 2]]

在Python中,当您将列表乘以正整数n时,得到n(浅) 列表中项目的副本。因此,[df]*2会生成一个列表,其中包含两个df副本。

现在考虑zip(*[df]*2)

*中使用的zip(*...)具有特殊含义。它告诉Python将*之后的列表解压缩到要传递给zip的参数中。因此,zip(*[df]*2)完全等同于zip(df, df)

In [3]: zip(df, df)
Out[3]: [(1, 1), (2, 2)]

In [4]: zip(*[df]*2)
Out[4]: [(1, 1), (2, 2)]

A more complete explanation of argument unpacking is given by SaltyCrane here

记下what zip is doingzip(*[df]*2)剥离两个副本的第一个元素(在这种情况下均为1), 形成元组,(1,1)。然后它剥离两个副本的第二个元素(两个都是2),并形成元组(2,2)。它返回一个包含这些元组的列表。

现在考虑当df是迭代器时会发生什么。迭代器有点像列表,除了迭代器只适用于一次传递。当项目从迭代器中拉出时,迭代器永远不会被重绕。

例如,文件句柄是迭代器。 假设我们有一个带行

的文件
1
2
3
4

In [8]: f = open('data')

您可以通过调用f将项目从迭代器next(f)中拉出来:

In [9]: next(f)
Out[9]: '1\n'

In [10]: next(f)
Out[10]: '2\n'

In [11]: next(f)
Out[11]: '3\n'

In [12]: next(f)
Out[12]: '4\n'

每次调用next(f)时,我们都会从文件句柄f获取下一行。 如果我们再次调用next(f),我们会得到一个StopIteration异常,表明迭代器是空的。

现在让我们看看石斑鱼配方在f上的行为:

In [14]: f = open('data')  # Notice we have to open the file again, since the old iterator is empty

In [15]: [f]*2
Out[15]: 
[<open file 'data', mode 'r' at 0xa028f98>,
 <open file 'data', mode 'r' at 0xa028f98>]

[f]*2为我们提供了一个列表,其中包含两个相同迭代器f相同副本。

In [16]: zip(*[f]*2)
Out[16]: [('1\n', '2\n'), ('3\n', '4\n')]

zip(*[f]*2)剥离第一个迭代器f中的第一个项目,然后 从第二个迭代器f剥离第一个项目。 但迭代器是 两次都是f并且因为迭代器对于单次通过是好的(你可以 永不回头),每次剥离物品时都会得到不同的物品。 zip是 每次都要调出next(f)来剥离一件物品。所以第一个元组是 ('1\n', '2\n')。同样,zip然后剥离第一个下一个项目 迭代器f,以及第二个迭代器f中的下一个项,并形成 元组('3\n', '4\n')。因此,zip(*[f]*2)返回 [('1\n', '2\n'), ('3\n', '4\n')]

这就是石斑鱼食谱的全部内容。在上面,我选择使用IT.izip而不是zip,以便Python返回迭代器而不是元组列表。如果文件中有很多行,这将节省大量内存。 zipIT.izip之间的差异更加全面地解释了here

答案 2 :(得分:1)

你不能使用:

min(number)

您只能使用:

min(num1, num2)

如果您的文件如下所示:

6238
0.5678
0.6874
0.7680
0.7834

您可以使用此代码:

Num1 = float(file.readline())

for line in file:
    Num2 = float(line)
    Num1 = min(Num1, Num2)

如果你有"Over" s,那么你可以跳过每一行。

答案 3 :(得分:0)

您需要读取文件的所有行,可能使用File.readlines(),或者您已经拥有的循环,然后为每行读取数字(如果是数字)并与“最佳”进行比较到目前为止“价值。

看起来你真的不需要split()。你需要做的是检查每一行是否以数字开头。如果是这样,您可以使用float(行)获取数字。如果空格引起麻烦,可能是float(line.strip())。如果该行不以数字开头,请将其保存在临时变量中。如果下一行证明提供的数字低于最佳最佳值,则可以将该临时值复制到临时输出的变量中。

答案 4 :(得分:0)

我在上面看到了一些有趣的解决方案。我会选择这个直截了当的解决方案。还有一个问题,那就是整数也可能是这样的。有人解决这个问题吗?

    df=open('myfile.txt')
    lines=df.readlines()
    minval = 1e99
    for n,line in enumerate(lines):
        try: 
            val=float(line)  # NB! like this, also integers will be taken. 
            if val < minval:  
                minval = val
                i_min  = n  
        except:
            pass
    word = lines[i_min-1]