【问题标题】:Iterate through list of dictionaries with conditions遍历具有条件的字典列表
【发布时间】:2017-09-11 05:29:40
【问题描述】:

假设 test 是一个很大的字典列表(这只是一个示例):

  test = [
{'alignedWord': 'welcome',
  'case': 'success',
  'end': 0.9400000000000001,
  'start': 0.56
  'word': 'Welcome'},

 {'alignedWord': 'to',
  'case': 'success',
  'end': 1.01,
  'start': 0.94,
  'word': 'to'},

 {'alignedWord': 'story',
  'case': 'not-found-in-audio',
  'word': 'Story'},

 {'alignedWord': 'in',
  'case': 'success',
  'end': 1.4100000000000001,
  'start': 1.34,
  'word': 'in'},

 {'alignedWord': 'a',
  'case': 'success',
  'end': 1.44,
  'start': 1.41,
  'word': 'a'},

 {'alignedWord': 'bottle',
  'case': 'success',
  'end': 1.78,
  'start': 1.44,
  'word': 'Bottle'} ]

`case =='success' 和 duration_s

Output:

{"text": "Welcome to", "duration_s": 0.45}
{"text": "in a bottle", "duration_s': 0.44}

duration = ('end' - 'start') #of the text

【问题讨论】:

  • 如果您希望有人指导您完成某件事,Stack Overflow 不是您寻找的地方。对于这种格式,指导您完成某些事情需要太多的来回交互; Stack Overflow 更多的是用于“提出具体的、有针对性的问题、获得答案、结束互动”。
  • 因此,请尝试在上面实现您的伪代码,并在遇到特定问题时联系我们。
  • 欢迎来到 SO。这是一个比大多数新用户发布的更好的问题,所以不要难过。我对如何编辑您的问题的建议:提供您的代码给出的输出,并提供您希望输出的内容。然后,既然你已经给了我们字典列表,人们可以尝试代码并确认他们已经得到了你想要的输出。当我们有您的数据和所需的上下文输出时,解释您所需的逻辑也需要更少的文本。
  • 使用索引对列表进行迭代非常不符合 Python 风格。在 Python 中——在大多数情况下——你直接迭代可迭代对象
  • @MaxPower 谢谢,这更有意义。会的。

标签: python json list loops dictionary


【解决方案1】:

我在测试列表中间添加了一个没有startend 键的新字典,现在这对你有用吗?正如您所澄清的,我还更改了滚动的持续时间。

from collections import OrderedDict

# add 'duration' var to dicts (makes code in loop clearer)
for dict_ in list_of_dicts:
  try:
    dict_.update({'duration': dict_['end'] - dict_['start']})
  except KeyError:
    dict_['duration'] = 999


# initialize result_dict with keys we'll add to
rolling_duration = 0
result_dict = OrderedDict([('text', ''), ('duration', 0)])

# looping directly through objects as mentioned in comments
for dict_ in list_of_dicts:
  rolling_duration = rolling_duration + dict_['duration']
  #print(dict_['word'], dict_['duration'], rolling_duration)

  if dict_['case'] == 'success' and rolling_duration < 10:
    result_dict['text'] = (result_dict['text'] + " " + dict_['word']).lstrip()
    result_dict['duration'] = round(rolling_duration, 2)

  # print accrued results and reset dict / rolling duration
  else:
    if result_dict['text'] != '':
      print(json.dumps(result_dict))
    result_dict = OrderedDict([('text', ''), ('duration', 0)])
    rolling_duration = 0

# print final json result_dict after exiting loop
print(json.dumps(result_dict))

{"text": "Welcome to", "duration": 0.45}

{"text": "in a Bottle","duration": 0.44}

【讨论】:

  • 这是一个很好的开始,谢谢。当我的列表超过 155 个项目时,它给了我一个错误。它适用于我提供的样本集。同样对于持续时间,我认为我解释得不够好,持续时间必须针对整个文本块,小于 10,如果文本块超过 10,我想在相同条件下开始一个新块。跨度>
  • Traceback (most recent call last): File "/Users/TracyShields/Scribie/Podcast-Data/new_align.py", line 22, in &lt;module&gt; dict_.update({'duration': dict_['end'] - dict_['start']}) KeyError: 'end' 当我的列表太大时,我会收到这个错误。
  • 您的第二点是一个简单的修改。只需跟踪 rolling_duration 变量(不在任何字典中)并将其包含在 if 条件的条件中。
  • 您遇到的错误是您的词典列表中的一个词典没有end 条目。你能确认这是真的吗?假设是,当我们遇到没有end 字段的字典时,您想如何更新duration
  • 是的,这是真的。在我的示例数据中,我搞砸了我的示例数据。当case=='not-found-in-audio' 没有endstart 时。我很抱歉。
【解决方案2】:

这可以使用根据需要生成最终字典的生成器来解决:

def split(it):
    it = iter(it)
    acc, duration = [], 0  # defaults
    for item in it:
        if item['case'] != 'success':   # split when there's a non-success
            if acc:
                yield {'text': ' '.join(acc), 'duration': duration}
                acc, duration = [], 0  # reset defaults

        else:
            tmp_duration = item['end'] - item['start']

            if tmp_duration + duration >= 10:  # split when the duration is too long
                if acc:
                    yield {'text': ' '.join(acc), 'duration': duration}
                acc, duration = [item['word']], tmp_duration  # new defaults

            else:
                acc.append(item['word'])
                duration += tmp_duration

    if acc:  # give the remaining items
        yield {'text': ' '.join(acc), 'duration': duration}

一个简单的测试给出:

>>> list(split(test))
[{'duration': 0.45000000000000007, 'text': 'Welcome to'},
 {'duration': 0.44000000000000017, 'text': 'in a Bottle'}]

这可以很容易地转储到 JSON 文件中:

>>> import json
>>> json.dumps(list(split(test)))
'[{"text": "Welcome to", "duration": 0.45000000000000007}, {"text": "in a Bottle", "duration": 0.44000000000000017}]'

【讨论】:

    猜你喜欢
    • 2013-08-19
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    相关资源
    最近更新 更多