我有一个对象列表,每个对象包含flag
(布尔值)和value
(整数)。每个列表项的值都在增加。我想将列表转换为一个新列表,只有每次flag属性交替时的第一个和最后一个value属性(间隔)。
换句话说,我想转换这个
[
{'flag': True, 'value': 0},
{'flag': True, 'value': 5},
{'flag': True, 'value': 10},
{'flag': False, 'value': 15},
{'flag': False, 'value': 20},
{'flag': False, 'value': 25},
{'flag': False, 'value': 30},
{'flag': False, 'value': 35},
{'flag': False, 'value': 40},
{'flag': True, 'value': 45},
{'flag': True, 'value': 50},
{'flag': True, 'value': 55},
{'flag': True, 'value': 60},
{'flag': False, 'value': 65},
{'flag': False, 'value': 70},
{'flag': False, 'value': 75},
{'flag': False, 'value': 80},
{'flag': False, 'value': 85},
{'flag': True, 'value': 90},
{'flag': True, 'value': 95}
]
进入这个(或类似的东西):
[
{'flag': True, 'values': (0, 10)},
{'flag': False, 'values': (15, 40)},
{'flag': True, 'values': (45, 60)},
{'flag': False, 'values': (65, 85)},
{'flag': True, 'values': (90, 95)},
]
在Python中解决这个问题的简单而优雅的方法是什么?
我希望示例数据不会太混乱。我尝试使用for-loop和使用reduce来解决这个问题,但两种解决方案似乎都没有。
谢谢!
答案 0 :(得分:3)
您可以使用itertools.groupby
按flag
对项目进行分组,然后将这些组转换为列表,并获取这些列表的第一个和最后一个元素的值。在这里,lst
是您的原始列表。
>>> [{"flag": key, "values" : (val[0]["value"], val[-1]["value"])}
... for key, val in ((key, list(val)) for key, val in itertools.groupby(lst, key=lambda d: d["flag"]))]
[{'flag': True, 'values': (0, 10)},
{'flag': False, 'values': (15, 40)},
{'flag': True, 'values': (45, 60)},
{'flag': False, 'values': (65, 85)},
{'flag': True, 'values': (90, 95)}]
或者类似地,使用内部列表解析首先提取value
键,因为我们必须使用内部生成器表达式将组迭代器转换为列表。结果是一样的。
>>> [{"flag": key, "values" : (vals[0], vals[-1])}
... for key, vals in ((key, [g["value"] for g in grp])
... for key, grp in itertools.groupby(lst, key=lambda d: d["flag"]))]
但这仍然远远不可读,所以我建议将其分为两行:
>>> groups = ((key, [g["value"] for g in grp])
... for key, grp in itertools.groupby(lst, key=lambda d: d["flag"]))
>>> result = [{"flag": key, "values" : (vals[0], vals[-1])} for key, vals in groups]
答案 1 :(得分:0)
熊猫解决方案:
j = [
{'flag': True, 'value': 0}, {'flag': True, 'value': 5},
{'flag': True, 'value': 10}, {'flag': False, 'value': 15},
{'flag': False, 'value': 20}, {'flag': False, 'value': 25},
{'flag': False, 'value': 30}, {'flag': False, 'value': 35},
{'flag': False, 'value': 40}, {'flag': True, 'value': 45},
{'flag': True, 'value': 50}, {'flag': True, 'value': 55},
{'flag': True, 'value': 60}, {'flag': False, 'value': 65},
{'flag': False, 'value': 70}, {'flag': False, 'value': 75},
{'flag': False, 'value': 80}, {'flag': False, 'value': 85},
{'flag': True, 'value': 90}, {'flag': True, 'value': 95}]
import pandas as pd
df = pd.DataFrame(j)
df['group'] = df['flag'].ne(df['flag'].shift()).cumsum() # column to groupby
output = df.groupby("group").apply(lambda x: \
{'flag':x["flag"].tolist()[0],
'values':(x["value"].min(),x["value"].max())})
output.tolist()
输出:
[{'flag': True, 'values': (0, 10)},
{'flag': False, 'values': (15, 40)},
{'flag': True, 'values': (45, 60)},
{'flag': False, 'values': (65, 85)},
{'flag': True, 'values': (90, 95)}]
Dataframe看起来像:
flag value group
0 True 0 1
1 True 5 1
2 True 10 1
3 False 15 2
4 False 20 2
5 False 25 2
6 False 30 2
7 False 35 2
8 False 40 2
9 True 45 3
...
答案 2 :(得分:0)
手动解决方案:
FirefoxOptions firefoxOptions = new FirefoxOptions();
firefoxOptions.setCapability("marionette", true);
webdriver = new FirefoxDriver(firefoxOptions);