ترتيب عناصر قوائم متعددة من قبل عددهم في بيثون
سؤال
أريد ترتيب قوائم متعددة وفقا لعناصرهم كم عدد مرات ظهورها في كل قائمة. مثال:
List1 = 1،2،3،4.
List2 = 4،5،6،7.
list3 = 4،1،8،9.
النتيجة = 4،1،2،3،4،5،6،6،6،8 (4 يحسب ثلاث مرات، 1 مرتين والباقي مرة واحدة)
لقد جربت ما يلي ولكني بحاجة إلى شيء أكثر ذكاء وشيء يمكنني القيام به مع أي القوائم.
l = []
l.append([ 1, 2, 3, 4, 5])
l.append([ 1, 9, 3, 4, 5])
l.append([ 1, 10, 8, 4, 5])
l.append([ 1, 12, 13, 7, 5])
l.append([ 1, 14, 13, 13, 6])
x1 = set(l[0]) & set(l[1]) & set(l[2]) & set(l[3])
x2 = set(l[0]) & set(l[1]) & set(l[2]) & set(l[4])
x3 = set(l[0]) & set(l[1]) & set(l[3]) & set(l[4])
x4 = set(l[0]) & set(l[2]) & set(l[3]) & set(l[4])
x5 = set(l[1]) & set(l[2]) & set(l[3]) & set(l[4])
set1 = set(x1) | set(x2) | set(x3) | set(x4) | set(x5)
a1 = list(set(l[0]) & set(l[1]) & set(l[2]) & set(l[3]) & set(l[4]))
a2 = getDifference(list(set1),a1)
print a1
print a2
الآن هنا هي المشكلة ... يمكنني أن أفعل ذلك مرارا وتكرارا مع A3 و A4 و A5 ولكنها معقدة للغاية إذن، أحتاج إلى وظيفة لهذا ... لكنني لا أعرف كيف ... الرياضيات عالقة ؛)
حلها: شكرا جزيلا للمناقشة. كأبى أحب هذا النظام بطريقة أو بأخرى: سريع + بالمعلومات. لقد ساعدني كل شيء! طن
المحلول
import collections
data = [
[1, 2, 3, 4, 5],
[1, 9, 3, 4, 5],
[1, 10, 8, 4, 5],
[1, 12, 13, 7, 5],
[1, 14, 13, 13, 6],
]
def sorted_by_count(lists):
counts = collections.defaultdict(int)
for L in lists:
for n in L:
counts[n] += 1
return [num for num, count in
sorted(counts.items(),
key=lambda k_v: (k_v[1], k_v[0]),
reverse=True)]
print sorted_by_count(data)
الآن دعونا تعميمها (لاتخاذ أي متطلبات قابلة للتوجيهية وتخفيف)، اسمح لمعايير المفتاح والعكس (لمطابقة فرزها)، وإعادة تسمية freq_sorted.:
def freq_sorted(iterable, key=None, reverse=False, include_freq=False):
"""Return a list of items from iterable sorted by frequency.
If include_freq, (item, freq) is returned instead of item.
key(item) must be hashable, but items need not be.
*Higher* frequencies are returned first. Within the same frequency group,
items are ordered according to key(item).
"""
if key is None:
key = lambda x: x
key_counts = collections.defaultdict(int)
items = {}
for n in iterable:
k = key(n)
key_counts[k] += 1
items.setdefault(k, n)
if include_freq:
def get_item(k, c):
return items[k], c
else:
def get_item(k, c):
return items[k]
return [get_item(k, c) for k, c in
sorted(key_counts.items(),
key=lambda kc: (-kc[1], kc[0]),
reverse=reverse)]
مثال:
>>> import itertools
>>> print freq_sorted(itertools.chain.from_iterable(data))
[1, 5, 4, 13, 3, 2, 6, 7, 8, 9, 10, 12, 14]
>>> print freq_sorted(itertools.chain.from_iterable(data), include_freq=True)
# (slightly reformatted)
[(1, 5),
(5, 4),
(4, 3), (13, 3),
(3, 2),
(2, 1), (6, 1), (7, 1), (8, 1), (9, 1), (10, 1), (12, 1), (14, 1)]
نصائح أخرى
الجمع بين اثنين من الأفكار نشرت بالفعل:
from itertools import chain
from collections import defaultdict
def frequency(*lists):
counter = defaultdict(int)
for x in chain(*lists):
counter[x] += 1
return [key for (key, value) in
sorted(counter.items(), key=lambda kv: (kv[1], kv[0]), reverse=True)]
ملاحظات:
- في بيثون 2.7، يمكنك استخدام
Counter
بدلا منdefaultdict(int)
. - يأخذ هذا الإصدار أي عدد من القوائم كوسيطة لها؛ العلامة النجمية الرائدة تعني أن تكون جميعا معبأة في tuple. إذا كنت ترغب في تمرير قائمة واحدة تحتوي على جميع قوائمك، حذفت تلك النجمة الرائدة.
- هذا الاستراحات إذا كانت قوائمك تحتوي على نوع غير قابل للنشر.
def items_ordered_by_frequency(*lists):
# get a flat list with all the values
biglist = []
for x in lists:
biglist += x
# sort it in reverse order by frequency
return sorted(set(biglist),
key=lambda x: biglist.count(x),
reverse=True)
جرب هذه:
def rank(*lists):
d = dict()
for lst in lists:
for e in lst:
if e in d: d[e] += 1
else: d[e] = 1
return [j[1] for j in sorted([(d[i],i) for i in d], reverse=True)]
مثال الاستخدام:
a = [1,2,3,4]
b = [4,5,6,7]
c = [4,1,8,9]
print rank(a,b,c)
يمكنك استخدام أي عدد من القوائم كمدخلات
يمكنك حساب عدد مظاهر كل عنصر (رسم بياني)، ثم الترتيب حسب ذلك:
def histogram(enumerable):
result = {}
for x in enumerable:
result.setdefault(x, 0)
result[x] += 1
return result
lists = [ [1,2,3,4], [4,5,6,7], ... ]
from itertools import chain
h = histogram(chain(*lists))
ranked = sorted(set(chain(*lists)), key = lambda x : h[x], reverse = True)
جرب هذا الرمز:
def elementFreq(myList):
#myList is the list of lists
from collections import Counter
tmp = []
for i in myList: tmp += i
return(Counter(tmp))
ملاحظة: يجب أن تكون قوائمك نوعا شائعا