Memberi peringkat Elemen dari beberapa Daftar berdasarkan jumlah mereka dengan Python

Saya ingin memberi peringkat pada beberapa daftar berdasarkan elemennya, seberapa sering daftar tersebut muncul di setiap daftar. Contoh:

daftar1 = 1,2,3,4
daftar2 = 4,5,6,7
daftar3 = 4,1,8,9

hasil = 4,1,2,3,4,5,6,7,8 (4 dihitung tiga kali, 1 dua kali dan sisanya satu kali)

Saya sudah mencoba yang berikut ini tetapi saya memerlukan sesuatu yang lebih cerdas dan sesuatu yang dapat saya lakukan dengan jumlah daftar berapa pun.


 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

Sekarang inilah masalahnya... Saya dapat melakukannya lagi dan lagi dengan a3,a4 dan a5 tetapi itu terlalu rumit, saya memerlukan fungsi untuk ini... Tapi saya tidak tahu caranya... Matematika saya macet ;)

ASK: terima kasih banyak atas diskusinya. Sebagai pemula saya menyukai sistem ini: cepat+informatif. Anda membantu saya sekuat tenaga! kamu


person Tom Siwik    schedule 01.12.2009    source sumber


Jawaban (6)


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)

Sekarang mari kita menggeneralisasikannya (untuk mengambil persyaratan hashable yang dapat diubah dan dilonggarkan), mengizinkan parameter kunci dan membalikkan (untuk mencocokkan pengurutan), dan mengganti namanya menjadi 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)]

Contoh:

>>> 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)]
person Community    schedule 01.12.2009
comment
saya tidak dapat memutuskan solusi mana yang tercepat. 2 fornya adalah = O(n**2) tapi bagaimana cara membuatnya lebih cepat.. :/ - person Tom Siwik; 02.12.2009
comment
Kalahkan aku. Milik Anda adalah satu-satunya (kecuali milik saya, tapi saya menyalin milik Anda) yang menerapkan urutan kedua, yang merupakan sentuhan yang bagus. - person Robert Rossney; 02.12.2009
comment
Bukan dua perulangan for yang membuat beberapa jawaban ini menjadi O(n^2), sedangkan jawaban ini bukan. Itu memanggil count(x) pada setiap item dalam daftar berantai yang menjadikannya O(n^2). - person Robert Rossney; 02.12.2009
comment
proxylittle: n menjadi jumlah panjang setiap daftar di lists berarti loop for saya yang bersarang masih hanya O(n), atau setiap item dari data asli hanya diproses satu kali (penyederhanaan besar, tidak sepenuhnya benar, tetapi O(2n ) masih O(n)). Pengurutannya juga adalah O(m log m) dan pemahaman daftar terakhir adalah O(m) (di mana m adalah jumlah item unik), sehingga keseluruhan fungsinya adalah O(n log n) (m tidak boleh lebih besar dari n) . Meskipun demikian, solusi tercepat masih bergantung pada cara penerapannya dan karakteristik masukannya, namun kompleksitas algoritmiknya tergantung pada cara Anda menggeneralisasikannya. - person ; 02.12.2009

Menggabungkan beberapa ide yang sudah diposting:

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)]

Catatan:

  1. Di Python 2.7, Anda dapat menggunakan Counter alih-alih defaultdict(int).
  2. Versi ini menggunakan sejumlah daftar sebagai argumennya; tanda bintang di depan berarti semuanya akan dimasukkan ke dalam tupel. Jika Anda ingin memasukkan satu daftar yang berisi semua daftar Anda, hilangkan tanda bintang di depannya.
  3. Ini rusak jika daftar Anda berisi tipe yang tidak dapat dihash.
person Robert Rossney    schedule 01.12.2009

Coba yang ini:

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)]

Contoh penggunaan:

a = [1,2,3,4]
b = [4,5,6,7]
c = [4,1,8,9]

print rank(a,b,c)

Anda dapat menggunakan sejumlah daftar sebagai masukan

person Andrea Ambu    schedule 01.12.2009

Anda dapat menghitung jumlah kemunculan tiap elemen (histogram), lalu mengurutkannya berdasarkan:

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)
person orip    schedule 01.12.2009
comment
Anda mengulangi rantai daftar dua kali di sini. Jika Anda mengurutkan histogram, Anda hanya perlu mengulanginya satu kali. (Selain itu, Anda tidak perlu membuat satu set, karena Anda sudah melakukannya.) - person Robert Rossney; 02.12.2009
comment
@Robert - Anda benar, tetapi efisiensi bukan satu-satunya perhatian. Menurut saya penggunaan tombol histogram membingungkan - tentu saja jika ini merupakan hambatan, saya tidak akan ragu. - person orip; 02.12.2009

Coba kode ini:

def elementFreq(myList):
    #myList is the list of lists
    from collections import Counter
    tmp = []
    for i in myList: tmp += i        
    return(Counter(tmp))

Catatan: Daftar Anda harus bertipe hashable

person Ashutosh    schedule 30.10.2018

person    schedule
comment
Bagus O(n**2), ah, betapa aku merindukanmu. - person ; 02.12.2009
comment
Dia tidak bilang dia menginginkannya secepat kilat. Ini hanya dimaksudkan untuk menjadi sederhana. - person twneale; 02.12.2009
comment
Benar, tetapi masalah dengan O(n^2) adalah bahwa lompatan dari tidak secepat kilat ke sangat lambat sangat mudah dilakukan. - person Robert Rossney; 02.12.2009
comment
ah.. baiklah... lebih cepat lebih baik. - person Tom Siwik; 02.12.2009