Encontrando el flotador más pequeño en el archivo, luego imprimiendo eso y una línea sobre él

Mi archivo de datos se ve así:

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

Lo que quiero hacer es seleccionar el flotador más pequeño y la palabra que está directamente sobre él e imprimir esos dos valores. No tengo ni idea de lo que estoy haciendo. He intentado

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

Cuál es mi bash de al menos intentar aislar el flotador más pequeño. El problema es que me está dando el último valor. Creo que ese es un problema porque Python no sabe comenzar de nuevo con la iteración, pero nuevamente … no tengo idea de lo que estoy haciendo. Intenté df2=min(df1.seek(0)) sin éxito, obtuve un error diciendo que no attribute seek . Así que eso es lo que he intentado hasta ahora, todavía no tengo idea de cómo imprimir la fila que vendría antes del flotador más pequeño. Se agradecerán sugerencias / ayuda / consejos, gracias.

Como nota al margen: este archivo de datos es un ejemplo de uno más grande con características similares, pero la palabra ‘Sobre’ también podría ser ‘Debajo’, por eso también debo imprimirlo.

Almacene los elementos en una lista de listas, [word,num] pares y luego aplique min en esa lista de listas. Use el parámetro key de min para especificar qué artículo debe usarse para la comparación de artículo:

 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 

Aquí lis ve así:

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

Puede usar la receta de izip(*[iterator]*2) , izip(*[iterator]*2) para agrupar las líneas en df en grupos de 2. Luego, para encontrar el par mínimo de líneas, use min y su parámetro key para especificar el proxy para usar comparación. En este caso, para cada par de líneas, (p, l) , queremos usar el flotante de la segunda línea, float(l) , como el proxy:

 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) 

huellas dactilares

 Over 0.5678 

Una explicación de la receta del mero:

Para comprender la receta del mero, primero observe qué sucede si df fuera una lista:

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

En Python, cuando multiplicas una lista por un entero positivo n , obtienes n copias (poco profundas) de los elementos de la lista. Así, [df]*2 hace una lista con dos copias de df dentro.

Ahora considere zip(*[df]*2)

El * usado en zip(*...) tiene un significado especial. Le dice a Python que descomprima la lista siguiendo el * en los argumentos que se pasarán a zip . Por lo tanto, zip(*[df]*2) es exactamente equivalente a 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)] 

SaltyCrane da una explicación más completa del desempaque de argumentos aquí .

Toma nota de lo que está haciendo zip . zip(*[df]*2) despega el primer elemento de ambas copias, (ambos en 1 en este caso), y forma la tupla, (1,1). Luego despega el segundo elemento de ambas copias (ambos 2) y forma la tupla (2,2). Devuelve una lista con estas tuplas dentro.

Ahora considera qué sucede cuando df es un iterador. Un iterador es algo así como una lista, excepto que un iterador es válido para una sola pasada. A medida que se extraen los elementos del iterador, el iterador nunca se puede rebobinar.

Por ejemplo, un identificador de archivo es un iterador. Supongamos que tenemos un archivo con líneas.

 1 2 3 4 In [8]: f = open('data') 

Puede sacar elementos del iterador f llamando a la 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' 

Cada vez que llamamos a la next(f) , obtenemos la siguiente línea del identificador de archivo, f . Si llamamos a next(f) nuevamente, obtendríamos una excepción StopIteration, que indica que el iterador está vacío.

Ahora veamos cómo se comporta la receta de mero en 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]: [, ] 

[f]*2 nos da una lista con dos copias idénticas del mismo iterador f .

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

zip(*[f]*2) despega el primer elemento del primer iterador, f , y luego despega el primer elemento del segundo iterador, f . ¡Pero el iterador es el mismo en ambas ocasiones! Y como los iteradores son buenos para una sola pasada (nunca puedes volver), obtienes diferentes elementos cada vez que despegas un elemento. zip está llamando a la next(f) cada vez para despegar un elemento. Así que la primera tupla es ('1\n', '2\n') . Del mismo modo, la zip despega el siguiente elemento del primer iterador f , y el siguiente elemento del segundo iterador f , y forma la tupla ('3\n', '4\n') . Por lo tanto, zip(*[f]*2) devuelve [('1\n', '2\n'), ('3\n', '4\n')] .

Eso es realmente todo lo que hay en la receta del mero. Arriba, elegí usar IT.izip lugar de zip para que Python devuelva un iterador en lugar de una lista de tuplas. Esto ahorraría mucha memoria si el archivo tuviera muchas líneas. La diferencia entre zip e IT.izip se explica más detalladamente aquí .

No puedes usar:

 min(number) 

Solo puedes usar:

 min(num1, num2) 

Si su archivo se ve así:

 6238 0.5678 0.6874 0.7680 0.7834 

Puedes usar este código:

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

Si tiene la "Over" , entonces puede saltar cada segunda línea.

Debe leer todas las líneas del archivo, tal vez con File.readlines (), o un bucle como el que ya tiene, y luego, para cada línea, lea el número (si es un número) y compare con “el mejor hasta ahora” valor.

Parece que realmente no necesitas dividir (). Lo que debe hacer es verificar si cada línea comienza con un dígito. Si es así, puede obtener el número con float (línea). Tal vez flotar (line.strip ()) si el espacio en blanco está causando problemas. Si la línea no comienza con un dígito, manténgala en una variable temporal. Si la siguiente línea demuestra ofrecer un número más bajo que el mejor valor hasta el momento, puede copiar ese valor temporal en una variable para la salida tentativa.

Veo algunas soluciones interesantes arriba. Iría por esta solución directa. Hay un problema que queda, que es que los enteros también pueden tomarse de esta manera. ¿Alguien una solución para esto?

  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]