Tôi đã thấy rất nhiều câu hỏi về việc loại bỏ các bản sao khỏi danh sách và đếm chúng. Nhưng tôi đang cố gắng tìm ra cách tốt nhất để nhóm chúng - cho một danh sách danh sách.
Đưa ra ví dụ này, tôi muốn nhóm theo trường thứ ba:
[[1, "text", "name1", "text"],
[2, "text", "name2", "text"],
[3, "text", "name2", "text"],
[4, "text", "name1", "text"]]
Tôi muốn có được điều này:
[[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
Tôi có thể nghĩ về cách ngây thơ bằng cách lặp đi qua và chỉ theo dõi những gì được tìm thấy [o [n^2]]. Nhưng tôi sẽ cho rằng có một cách tốt hơn.
Đã hỏi ngày 6 tháng 5 năm 2015 lúc 18:07May 6, 2015 at 18:07
0
Bạn có thể sắp xếp và sử dụng Groupby nhưng đó là
[[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
1:from operator import itemgetter
from itertools import groupby
print[[list[v] for _,v in groupby[ sorted[l,key=itemgetter[2]],itemgetter[2]]]]
Hoặc sử dụng nhóm được đặt hàng theo phần tử thứ ba cho giải pháp
[[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
2 bằng cách sử dụng phần tử thứ ba làm khóa và nối thêm các nhóm phụ làm giá trị. SetDefault sẽ xử lý các khóa lặp lại:from collections import OrderedDict
od = OrderedDict[]
for sub in l:
od.setdefault[sub[2],[]].append[sub]
from pprint import pprint as pp
pp[od.values[]]
[[[1, 'text', 'name1', 'text'], [4, 'text', 'name1', 'text']],
[[2, 'text', 'name2', 'text'], [3, 'text', 'name2', 'text']]]
Nếu đơn đặt hàng không quan trọng, bạn có thể sử dụng DefaultDict thay cho đơn đặt hàng.
Nếu đơn hàng không quan trọng, một DefaultDict là hiệu quả nhất.
In [7]: from itertools import groupby
In [8]: from collections import OrderedDict, defaultdict
In [9]: l = [[1, "text", "name{}".format[choice[list[range[2000]]]], "text"] for _ in xrange[40000]]
In [13]: from operator import itemgetter
In [14]: timeit [list[v] for _,v in groupby[ sorted[l,key=itemgetter[2]],itemgetter[2]]]
10 loops, best of 3: 42.5 ms per loop
In [15]: %%timeit
od = defaultdict[list]
for sub in l:
od[sub[2]].append[sub]
....:
100 loops, best of 3: 9.42 ms per loop
In [16]: %%timeit
od = OrderedDict[]
for sub in l:
od.setdefault[sub[2],[]].append[sub]
....:
10 loops, best of 3: 25.5 ms per loop
In [17]: lists = l
In [18]: %%timeit
....: groupers = set[l[2] for l in lists]
....: [filter[lambda x: x[2] == y, lists] for y in groupers]
....:
1 loops, best of 3: 8.48 s per loop
In [19]: timeit l = [filter[lambda x: x[2] == y, lists] for y in set[l[2] for l in lists]]
1 loops, best of 3: 8.29 s per loop
Vì vậy, nếu đơn hàng không quan trọng thì DefaultDict thắng, Groupby vẫn hoạt động khá tốt vì sắp xếp vẫn khá rẻ so với cách tiếp cận bậc hai. Như bạn có thể thấy độ phức tạp bậc hai của bộ lọc hoạt động xấu khi dữ liệu phát triển.
Đã trả lời ngày 6 tháng 5 năm 2015 lúc 18:13May 6, 2015 at 18:13
7
Bạn đi đây:
>>> lists = [[1, "text", "name1", "text"],
... [2, "text", "name2", "text"],
... [3, "text", "name2", "text"],
... [4, "text", "name1", "text"]]
>>> groupers = set[l[2] for l in lists]
>>> groupers
set[['name2', 'name1']]
>>> l = [filter[lambda x: x[2] == y, lists] for y in groupers]
>>> pprint.pprint[l]
[[[2, 'text', 'name2', 'text'], [3, 'text', 'name2', 'text']],
[[1, 'text', 'name1', 'text'], [4, 'text', 'name1', 'text']]]
Tất nhiên bạn có thể viết toàn bộ logic nhóm theo một dòng:
>>> l = [filter[lambda x: x[2] == y, lists] for y in set[l[2] for l in lists]]
>>> pprint.pprint[l]
[[[2, 'text', 'name2', 'text'], [3, 'text', 'name2', 'text']],
[[1, 'text', 'name1', 'text'], [4, 'text', 'name1', 'text']]]
Đã trả lời ngày 6 tháng 5 năm 2015 lúc 18:15May 6, 2015 at 18:15
Anshul Gidelanshul GidelAnshul Goyal
69.6K37 Huy hiệu vàng143 Huy hiệu bạc176 Huy hiệu đồng37 gold badges143 silver badges176 bronze badges
Sử dụng
[[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
3 với phần tử bạn muốn sắp xếp dưới dạng [[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
4 và [[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
5 cho nhóm 'em:>>> from itertools import groupby
>>> sl = sorted[your_list, key=lambda your_list: your_list[2]]
>>> [list[v] for k,v in groupby[sl, key=lambda sl:sl[2]]]
[[[1, 'text', 'name1', 'text'],
[4, 'text', 'name1', 'text']],
[[2, 'text', 'name2', 'text'],
[3, 'text', 'name2', 'text']]]
Đã trả lời ngày 6 tháng 5 năm 2015 lúc 19:44May 6, 2015 at 19:44
Shan Vallerushan ValleruShan Valleru
3.1031 Huy hiệu vàng21 Huy hiệu bạc21 Huy hiệu đồng1 gold badge21 silver badges21 bronze badges
2
Cách dễ nhất để làm điều đó là với đối số
[[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
4 của hàm [[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
7. Trong ví dụ của bạn:[[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
8[[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
9from operator import itemgetter
from itertools import groupby
print[[list[v] for _,v in groupby[ sorted[l,key=itemgetter[2]],itemgetter[2]]]]
0Bạn có thể tìm thêm thông tin về lập luận này trên liên kết này.
Đã trả lời ngày 6 tháng 5 năm 2015 lúc 18:18May 6, 2015 at 18:18
Tomasyanytomasyanytomasyany
1.0933 Huy hiệu vàng13 Huy hiệu bạc32 Huy hiệu đồng3 gold badges13 silver badges32 bronze badges
2
Chức năng sau sẽ nhanh chóng [không yêu cầu sắp xếp] Trình tự phụ của nhóm theo bất kỳ độ dài nào bằng khóa của chỉ mục được chỉ định:no sorting required] group sub-sequences of any length by a key of specified index:
# given a sequence of sequences like [[3,'c',6],[7,'a',2],[88,'c',4],[45,'a',0]],
# returns a dict grouping sequences by idx-th element - with idx=1 we have:
# if merge is True {'c':[3,6,88,4], 'a':[7,2,45,0]}
# if merge is False {'c':[[3,6],[88,4]], 'a':[[7,2],[45,0]]}
def group_by_idx[seqs,idx=0,merge=True]:
d = dict[]
for seq in seqs:
if isinstance[seq,tuple]: seq_kind = tuple
if isinstance[seq,list]: seq_kind = list
k = seq[idx]
v = d.get[k,seq_kind[]] + [seq[:idx]+seq[idx+1:] if merge else seq_kind[[seq[:idx]+seq[idx+1:],]]]
d.update[{k:v}]
return d
Trong trường hợp câu hỏi của bạn, chìa khóa là phần tử có chỉ mục 2, do đó
group_by_idx[your_list,2,False]
cho
[[[1, "text", "name1", "text"],
[4, "text", "name1", "text"]],
[[2, "text", "name2", "text"],
[3, "text", "name2", "text"]]]
0Mà không chính xác là đầu ra mà bạn yêu cầu, nhưng cũng có thể phù hợp với nhu cầu của bạn.
Đã trả lời ngày 13 tháng 6 năm 2016 lúc 13:57Jun 13, 2016 at 13:57
MMJMMJmmj
5.2312 Huy hiệu vàng41 Huy hiệu bạc48 Huy hiệu đồng2 gold badges41 silver badges48 bronze badges