Chinaunix

标题: 查找txt文件中第二列最大值 [打印本页]

作者: hothat007    时间: 2014-01-23 12:29
标题: 查找txt文件中第二列最大值
本帖最后由 hothat007 于 2014-01-23 13:39 编辑

DYC-P072-2 2014-01-21 12.zip (18.85 KB, 下载次数: 24) 新手学习Python不久,在编写查找文本中的最大值,但是代码出现问题,请大家指导谢谢
  1. #coding:utf-8

  2. import os

  3. filename = 'DYC-P072-2 2014-01-21 12.txt'
  4. fr = 28
  5. to = 29

  6. filepath = os.getcwd()
  7. fileaddress = filepath + '\\' + filename
  8. f = open(fileaddress)

  9. i = 1
  10. count = 0
  11. buf = ''
  12. num = 0

  13. for lines in f.readlines():
  14.     count = count + 1
  15.     line = lines.split()
  16.     if (float(line[0]) >= fr) and (float(line[0]) <= to):
  17.         if i == 1:
  18.             buf = line
  19.             i = 0
  20.         elif line[1] > buf[1]:
  21.             buf = line
  22.             num = count
  23.             print line[1]
  24.             print buf
  25.             os.system('pause')
  26.    
  27. print buf
  28. print num

  29. f.close()

  30. os.system('pause')



复制代码

如图我先查找到153这行数
可是我的代码运行结果却是这样的:


作者: hothat007    时间: 2014-01-23 12:32
fr=28
to=29
就是想查找第一列的范围,在这个范围里比较第二列的值,找最大的,可是找不到呢
作者: hothat007    时间: 2014-01-23 13:22
各位路过的留个名呗
作者: ssfjhh    时间: 2014-01-23 13:27
楼主,你是不是应该贴个测试用的数据呢?
作者: Hadron74    时间: 2014-01-23 13:28
你第25行代码没有对line[1]进行格式转换,它默认为按字符串比较了,改了就成了。
作者: q1208c    时间: 2014-01-23 13:32
楼主, 你弄个图上来, 我们没办法拿到你的测试数据. 总不成又来扣图吧?!
作者: ssfjhh    时间: 2014-01-23 13:36
本帖最后由 ssfjhh 于 2014-01-23 13:38 编辑

没看懂你那个条件判断中还想另外输出什么信息,这个代码只输出最大值。
  1. #coding:utf-8

  2. import os

  3. filename = 'DYC-P072-2 2014-01-21 12.txt'
  4. fr = 28
  5. to = 29

  6. #filepath = os.getcwd()
  7. #fileaddress = filepath + '\\' + filename
  8. with open(fileaddress, 'r') as f:
  9.     maxnum = 0

  10.     for lines in f.readlines():
  11.         count += + 1
  12.         line = lines.split()
  13.         if fr <= float[line[0] <= to and int(line[1]) > maxnum:
  14.             maxnum = int(line[1])
  15.     print(maxnum)

  16. os.system('pause')
复制代码

作者: murdercool    时间: 2014-01-23 13:37
  1. elif line[1] > buf[1]:
复制代码
需要加 int的吧
作者: hothat007    时间: 2014-01-23 13:37
回复 4# ssfjhh


    不好意思,我错了,马上贴不过,楼下的提示已经让我解决了问题,我想知道这个代码的抒写应该不是最好的,希望大家能够指正
作者: hothat007    时间: 2014-01-23 13:41
回复 5# Hadron74


谢谢,按你的意思已经解决,如果有空请指正代码哈,我感觉我写的不好

   
作者: hothat007    时间: 2014-01-23 13:42
回复 6# q1208c


    不好意思,以为代码简单不需要的,现已上传数据,谢谢!!
作者: hothat007    时间: 2014-01-23 13:43
回复 8# murdercool


    嗯嗯因为都是整数哈,谢谢
作者: hothat007    时间: 2014-01-23 13:45
回复 7# ssfjhh


    哈,太好了,我在研究一下您的代码,非常感谢!!
作者: hothat007    时间: 2014-01-23 13:46
回复 7# ssfjhh


    相比之下我的代码太繁琐,不符合python简洁的风格
作者: timespace    时间: 2014-01-23 13:48
回复 1# hothat007
虽然有很多写法,但楼主的写法不够Pythonic
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-

  3. import itertools

  4. def getitems(fobj):
  5.     for idx, line in enumerate(fobj):
  6.         items = line.split()
  7.         if len(items) != 2:
  8.             continue
  9.         # (行索引,一列浮点数,二列整数)
  10.         yield idx, float(items[0]), int(items[1])

  11. def main():

  12.     with open('tmp.txt') as fp:
  13.         print max(
  14.                 itertools.ifilter(
  15.                     lambda e: 28.0 <= e[1] <= 29.0,
  16.                     getitems(fp)),
  17.                 key=lambda e: e[2])

  18. if __name__ == '__main__':
  19.     main()
复制代码
附近是自己构造的测试数据,和你的应该类似,原理不变。 tmp.txt.gz (7.61 KB, 下载次数: 4)

   
作者: hothat007    时间: 2014-01-23 13:52
回复 15# timespace


    so cool!其实解决问题是最小的部分,更重要的是您给我提示,我也觉得自己写的不够python,您的回复太给力了
作者: ssfjhh    时间: 2014-01-23 14:07
最近论坛里的人明显多起来了,至少python版是这样的,大家都已经放假了吗?
作者: hothat007    时间: 2014-01-23 14:23
回复 17# ssfjhh


    差不多吧,活跃起来好呀,共同进步!!
作者: Hadron74    时间: 2014-01-23 15:03
回复 15# timespace


    这个好!
作者: hothat007    时间: 2014-01-23 18:57
回复 15# timespace


    但是数据中有多个相同大小的数,怎么办呢
作者: timespace    时间: 2014-01-23 20:28
本帖最后由 timespace 于 2014-01-23 20:30 编辑

回复 20# hothat007
看你需要什么,只要简单变通下前面的例子就可以了吧,当然前提是看懂前面那个例子。

1. 取最早出现的那个最大数。利用已有的行序号,修改max的key参数
  1. key=lambda e: (e[2], -e[0])
复制代码
2. 取最晚出现的那个最大数。开始的例子已经实现了。

3. 取所有的最大数。没有系统函数,那么自定义一个函数取代max,然后就会取出一个list,包含所有最大数
  1. def my_max(iterable, key):
  2.     maxs = [next(iterable)]
  3.     for e in iterable:
  4.         key_e, key_max = key(e), key(maxs[0])
  5.         if key_e > key_max:
  6.             maxs = [e]
  7.         elif key_e == key_max:
  8.             maxs.append(e)
  9.     return maxs
复制代码
建议还是多看看标准库的前几章,包含很多基本的迭代排序和数据结构,足以应付很多问题了。



   
作者: timespace    时间: 2014-01-23 21:50
本帖最后由 timespace 于 2014-01-23 21:51 编辑

其实当查询条件越来越复杂时,直接编码就很麻烦,不如用DB处理这种关系型数据。
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-

  3. import itertools
  4. import sqlite3

  5. def getitems(fobj):
  6.     for idx, line in enumerate(fobj):
  7.         items = line.split()
  8.         if len(items) != 2:
  9.             continue
  10.         # (行索引,一列浮点数,二列整数)
  11.         yield idx, float(items[0]), int(items[1])

  12. def main():
  13.     # 内存数据库统计
  14.     with open('tmp.txt') as fp, sqlite3.connect(':memory:') as con:
  15.         con.executescript('''
  16.             CREATE TABLE foo ( no, float, int );
  17.             CREATE INDEX bar ON foo ( float, int );
  18.         ''')
  19.         con.executemany('INSERT INTO foo VALUES(?,?,?)', getitems(fp))
  20.         for row in con.execute('SELECT no,float,int  FROM foo \
  21.                 WHERE float >= 28.0 and float <= 29.0 \
  22.                 ORDER BY int DESC LIMIT 10'):
  23.             print row

  24. if __name__ == '__main__':
  25.     main()
复制代码

作者: icymirror    时间: 2014-01-24 11:11
回复 1# hothat007

  1. def compareItem(item1, item2):
  2.     ''' Function provide 2nd column comparing method for reduce to use.'''
  3.     if int(item1.split()[1]) > int(item2.split()[1]):
  4.         return item1
  5.     else:
  6.         return item2

  7. def readRecords(filename):
  8.     ''' read all data from file for coming reduce to filter.'''
  9.     result = []
  10.     file_handle = open(filename)
  11.     for item in file_handle.readlines():
  12.         result.append(item)
  13.     return result

  14. def main():
  15.     data = readRecords('DYC-P072-2 2014-01-21 12.txt')
  16.     print(reduce(compareItem, data))

  17. if __name__ == '__main__':
  18.     main()
复制代码

作者: hothat007    时间: 2014-01-24 20:01
本帖最后由 hothat007 于 2014-01-24 20:02 编辑

回复 21# timespace


    [attach]652193[/attach]

好像不太对呀,原来的那个代码是提取的第一个最大值呀
作者: hothat007    时间: 2014-01-24 20:19
回复 21# timespace


    key=lambda e: (e[2], -e[0])这句怎么理解呀,理解不了了T_T
作者: timespace    时间: 2014-01-24 20:45
回复 24# hothat007
嗯,你说对了。更正下:
1.取最早的最大数,开始已实现。

2.取最晚的最大数,修改max的key参数为
  1. key=lambda e: (e[2], e[0])
复制代码

作者: timespace    时间: 2014-01-24 21:06
本帖最后由 timespace 于 2014-01-24 21:11 编辑

回复 25# hothat007
1. 理解max(..., key)执行的逻辑。顺序迭代,元素a和b比较等价于key(a)和key(b)比较,最终迭代完成时返回一个最大值。
  1. lambda e: (e[2], e[0])
复制代码
等价于
  1. def key(e):
  2.     return e[2], e[0] # 返回的是一个tuple
复制代码
2. 理解tuple比较的逻辑。简单说就是当tuple第i个元素已经可以比较出大小时,就不会再去比较第i+1个元素。下面的例子就可以看出这个特性:
  1. >>> max([(1, 1), (2, 2), (3, 2)], key=lambda e: e[1])
  2. (2, 2)
  3. >>> max([(1, 1), (2, 2), (3, 2)], key=lambda e: (e[1],e[0]))
  4. (3, 2)
  5. >>> max([(1, 1), (2, 2), (3, 2)], key=lambda e: (e[1],-e[0]))
  6. (2, 2)
  7. >>> max([(1, 1), (2, 2), (3, 2), (4, 0)], key=lambda e: (e[1],e[0]))
  8. (3, 2)
复制代码
3. 你的需求中,元素出现早晚可以用行序号表示,所以将e[0]作为比较参数,但它是次要关系。
作者: hothat007    时间: 2014-01-24 21:20
回复 27# timespace


    感动哭了,太给力了!!




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2