【问题标题】:Getting values from file if match found for lines with same id in Python如果在 Python 中为具有相同 id 的行找到匹配项,则从文件中获取值
【发布时间】:2014-03-20 20:59:51
【问题描述】:

我有一个包含数据行的文件。每一行都以一个 id 开头,然后是用逗号分隔的一组固定属性。

123,2,kent,...,
123,2,bob,...,
123,2,sarah,...,
123,8,may,...,

154,4,sheila,...,
154,4,jeff,...,

175,3,bob,...,

249,2,jack,...,
249,5,bob,...,
249,3,rose,...,

如果条件满足,我想获取一个属性。条件是如果 'bob' 出现在同一个 id 中,则获取后面的第二个属性的值。

For example:

id: 123
values returned: 2, 8

id: 249
values returned: 3

Java 有一个我可以使用的双循环,但我想在 Python 中尝试一下。任何建议都会很棒。

【问题讨论】:

  • 为什么 id 249 的values returned3 而不是2, 5, 3

标签: python for-loop file-io readlines


【解决方案1】:

我想出了一个(也许)更pythonic的解决方案,它使用groupbydropwhile。此方法产生与以下方法相同的结果,但我认为它更漂亮.. :) 标志、“curr_id”和类似的东西不是很pythonic,如果可能的话应该避免!

import csv
from itertools import groupby, dropwhile

goal = 'bob'
ids = {}

with open('my_data.csv') as ifile:
    reader = csv.reader(ifile)
    for key, rows in groupby(reader, key=lambda r: r[0]):
        matched_rows = list(dropwhile(lambda r: r[2] != goal, rows))
        if len(matched_rows) > 1:
            ids[key] = [row[1] for row in matched_rows[1:]]

print ids

(下面的第一个解决方案)

from collections import defaultdict
import csv

curr_id = None
found = False
goal = 'bob'
ids = defaultdict(list)

with open('my_data.csv') as ifile:
    for row in csv.reader(ifile):
        if row[0] != curr_id:
            found = False
            curr_id = row[0]
        if found:
            ids[curr_id].append(row[1])
        elif row[2] == goal:
            found = True

print dict(ids)

输出:

{'123': ['2', '8'], '249': ['3']}

【讨论】:

  • +1 啊,这比我类似的答案要好,但是它有一个 175 的空列表
  • @bernie 谢谢伙计,但我对这个解决方案不满意 - 我不喜欢使用标志、curr_id 和其他东西...... :)
  • @bernie 如果你感兴趣的话,我找到了另一个解决方案 :)
  • 非常干净。利用已经按 ID 排序的数据。
  • 感谢 Steinar Lima 的回答!它完全按照我的意愿工作,您能够弄清楚我试图读取的文件实际上是一个 csv。
【解决方案2】:

在循环时设置一个标志或其他东西:

name = 'bob'
id = '123'
found = False

for line in file:
    l = line.split(',')
    if l[0] == id:
        if l[2] == name:
            found = True
        if found:
            print l[1]

【讨论】:

    【解决方案3】:
    import csv, collections as co, cStringIO as StringIO
    
    s = '''123,2,kent,...,
    123,2,bob,...,
    123,2,sarah,...,
    123,8,may,...,
    154,4,sheila,...,
    154,4,jeff,...,
    175,3,bob,...,
    249,2,jack,...,
    249,5,bob,...,
    249,3,rose,...,'''
    
    filelikeobject = StringIO.StringIO(s)
    dd = co.defaultdict(list)
    cr = csv.reader(filelikeobject)
    for line in cr:
      if line[2] == 'bob':
        dd[line[0]]; continue
      if line[0] in dd:
        dd[line[0]].append(line[1])
    

    结果:

    >>> dd
    defaultdict(<type 'list'>, {'175': [], '123': ['2', '8'], '249': ['3']})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 2021-12-31
      相关资源
      最近更新 更多