我想根据属性的值将类的实例分组在一起。 假设我有以下课程:
class location:
def __init__(self,x_coord,y_coord,text):
self.x_coord=x_coord
self.y_coord=y_coord
self.text=text
def __repr___(self):
return self.text
mylist=[location(1,0,'Date'),location(5,0,'of'),location(8,0,'Entry'), location(28,0,'Date'),location(29,0,'of'),location(30,0,'Birth') ]
如果x_coord属性的差异小于10,我想对我的班级列表进行分组,这样
mygroupedlist=[['Date','of','Entry'],['Date','of','Birth']]
有人可以给我提示吗?
答案 0 :(得分:1)
如果您不介意使用外部库,则可以通过使用numpy和pandas获得更好的性能。
# Create a dataframe
df = pd.DataFrame(mylist, columns=['locations'])
# Create columns representing the 'x' coords, and the 'text'
df['x'] = df['locations'].apply(lambda x: x.x_coord)
df['text'] = df['locations'].apply(lambda x: x.text)
# Create an indicator array that tells you whether the current row is within 10 of the previous row
closeness_indicator = np.isclose(df['x'], df['x'].shift(1), atol=10)
# Negate that, then take the cumulative sum to get groups:
groups = (~closeness_indicator).cumsum()
# GRoup by that array, then create lists from the grouped text:
df.groupby(groups)[text].apply(list)
输出:
1 [Date, of, Entry]
2 [Date, of, Birth]
Name: text, dtype: object
答案 1 :(得分:0)
这是一个使用有状态函数来记住其最后看到的项目的解决方案。 (不要向任何函数式程序员展示此内容)。然后,我们可以在调用itertools.groupby
def grouper(key=lambda x: x, distance=10):
_marker = object()
last_seen = _marker
flag = True
def close_enough(item):
nonlocal last_seen, flag
if last_seen is _marker:
last_seen = key(item)
return flag
diff = abs(key(item) - last_seen)
last_seen = key(item)
if diff >= distance:
flag = not flag
return flag
return close_enough
[[i.text for i in g] for k, g in groupby(mylist, key=grouper(lambda x: x.x_coord))]
# [['Date', 'of', 'Entry'], ['Date', 'of', 'Birth']]
答案 2 :(得分:0)
我的尝试是使用每次变化大于或等于distance
时都会增加的计数器。这样,就可以轻松地将此生成器提供给groupby
:
def gen(lst, distance=10):
counter = 0
for cur, nxt in zip(lst[::1], lst[1::1]):
yield counter, cur
if abs(cur.x_coord - nxt.x_coord) >= distance:
counter += 1
yield counter, nxt
myGroupedList = [list(i[1] for i in g) for _, g in groupby(gen(mylist), lambda v: v[0])]
print(myGroupedList)
打印:
[[Date, of, Entry], [Date, of, Birth]]
答案 3 :(得分:0)
您可以使用defaultdict
列表并迭代对象列表,每当差异大于或等于10时就增加密钥。
该解决方案假定您的x_coord
属性在增加,即按升序排序。
from collections import defaultdict
d = defaultdict(list)
d[0].append(mylist[0])
for item in mylist[1:]:
last_key = len(d) - 1
if item.x_coord - next(reversed(d[last_key])).x_coord < 10:
d[last_key].append(item)
else:
d[last_key+1].append(item)
测试以检查订购是否正确:
res = [[i.x_coord for i in x] for x in d.values()]
print(res)
[[1, 5, 8], [28, 29, 30]]