Muayyan element bilan ro'yxatlarning sonini qanday qilib olaman?

Menga o'xshagan ro'yxatlar ro'yxati bor

listOfLists = [
    ['a','b','c','d'],
    ['a','b'],
    ['a','c'],
    ['c','c','c','c']  
 ] 

Men muayyan elementga ega bo'lgan ro'yxatlarning sonini hisoblashni istayman. Misol uchun, mening chiqishim bo'lishi kerak

{'a':3,'b':2,'c':3,'d':1}

Ko'rib turganingizdek, men elementlarning umumiy soniga muhtoj emasmiz. "c" holatlarida, umumiy soni 5 bo'lsa-da, chiqdi 3, faqat 3 ro'yxatda uchraydi.

Hisobni olish uchun hisoblagichdan foydalanaman. Xuddi shu narsani quyida ko'rish mumkin.

line_count_tags = []
for lists in lists_of_lists:
    s = set()
    for element in lists:
         s.add(t)
    lines_count_tags.append(list(s))

count = Counter([count for counts in lines_count_tags for count in counts])

Shunday qilib, hisoblarni chop etganda, men olaman

{'a':3,'c':3,'b':2,'d':1}

Maqsadimni amalga oshirish uchun juda yaxshi yo'l borligini bilmoqchiman.

9

7 javoblar

Taymer dan foydalaning va har bir ro'yxatni to'siqqa aylantiring . to'siq har bir ro'yxatdan har qanday replikatsiyalarni olib tashlaydi, shunda siz bir xil ro'yxatdagi ikki nusxadagi qiymatlarni hisoblamaysiz:

>>> from collections import Counter

>>> Counter(item for lst in listOfLists for item in set(lst))
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1})

Funktsional dasturlashni yoqtirsangiz, to'siq - xarita </​​code> pad listOfLists kodini zanjiri Taymerni :

>>> from collections import Counter
>>> from itertools import chain

>>> Counter(chain.from_iterable(map(set, listOfLists)))
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1})

Birinchi yondashuvga mutanosib bo'lgan (bir oz tezroq bo'lishi mumkin).

11
qo'shib qo'ydi

Counter ga yuborilgan jeneratör tushunchasini hisoblashdan oldin, har bir ro'yxatni to'siq sifatida aylantiraman:

import collections
print(collections.Counter(y for x in listOfLists for y in set(x)))

natija:

Counter({'a': 3, 'c': 3, 'b': 2, 'd': 1})

(bu sizning amaldagi amallaringizdir, lekin yuqoridagi kod bir nechta loop va vaqtinchalik ro'yxat yaratilishiga sabab bo'ladi)

9
qo'shib qo'ydi

Siz buni taymer holda ham qilishingiz mumkin:

result = {}
for lis in listOfLists:
    for element in set(lis):
        result[element] = result.get(element, 0) + 1
print result  # {'a': 3, 'c': 3, 'b': 2, 'd': 1}

Eng nafis emas, balki ancha tez bo'lishi kerak.

7
qo'shib qo'ydi

Counter yondashuvida itertools.chain.from_iterable kabi ko'rinishi mumkin

Counter(chain.from_iterable(map(set, listOfLists)))

Namoyish

>>> from itertools import chain
>>> from collections import Counter
>>> Counter(chain.from_iterable(map(set, listOfLists)))
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1})

Rough benchmark

%timeit Counter(item for lst in listOfLists for item in set(lst))
100000 loops, best of 3: 13.5 µs per loop

%timeit Counter(chain.from_iterable(map(set, listOfLists)))
100000 loops, best of 3: 12.4 µs per loop
5
qo'shib qo'ydi
CPython 2.7.11da itertools.chain (~ 40%!) Dan foydalanib, men juda tez bajaraman. Shunga qaramay Counter + itertools.chain taqdim etilgan raw usulidan 4 marta sekinroq ijro eting.
qo'shib qo'ydi muallif zwer, manba
Haqiqatan ham, mening joyimdagi tez farqni juda hayron qoldim, men itertools ga amal qilmaganman, aslida juda ko'p narsa - ular odatda asta-sekin, lekin o'qish osonroq tanlash: D
qo'shib qo'ydi muallif zwer, manba
@zwer Eh, biz qanday baho berishimizga bog'liq. Mening yechimim qo'shimcha xarajatlarga ega, lekin agar siz kirish hajmini oshirsangiz, u tezroq bo'lishi kerak. Aynan shuning uchun benchmarking juda muhim emas :)
qo'shib qo'ydi muallif miradulo, manba

Faqat to'siq ga aylantirilsin, itertools.chain.from_iterable dan foydalaning va counter ga joylashtiring.

from collections import Counter
from itertools import chain

inp = [
    ['a','b','c','d'],
    ['a','b'],
    ['a','c'],
    ['c','c','c','c']  
 ] 


print(Counter(chain.from_iterable(map(set, inp))))
3
qo'shib qo'ydi

Ushbu yondashuv, listOfLists -ga kiritilgan tushunchani ishlatib, noyob kirimlarni hisoblab chiqadi va keyin lug'atni tushunish yordamida har bir ro'yxatdagi ziddiyatlarni hisoblaydi

A = {val for s in listOfLists for val in s}
d = {i: sum( i in j for j in listOfLists) for i in A}
print(d) # {'a': 3, 'c': 3, 'b': 2, 'd': 1}

Men buni bir oz yomon deb tan olaman, lekin bu mumkin bo'lgan echim (va lug'atni tushunishdan salqin foydalanish). Bundan tashqari, uni A hisoblashni lug'at tushunchasiga kiritib, uni bir marta bajarishingiz mumkin.

2
qo'shib qo'ydi
Sizning to'siqingizni A ga qayta tiklashingiz yoki ro'yxatni ro'yxatni tushunish bilan to'ldirishga hojat yo'q, avlod ifodasi yaxshiroq ... aslida A ni yaratishingiz mumkin ham tushunarli tushunish
qo'shib qo'ydi muallif Copperfield, manba
@Copperfield Taklifingiz uchun tashakkur. Men o'zgarishlar qildim.
qo'shib qo'ydi muallif nbryans, manba

Looplarni ishlatadigan yana bir versiya:

listOfLists = [
    ['a','b','c','d'],
    ['a','b'],
    ['a','c'],
    ['c','c','c','c']
    ]

final = {}
for lst in listOfLists:
    for letter in lst:
        if letter in final:
            final[letter] += 1
        else:
            final[letter] = 1

Shunday qilib, yakuniy deb nomlangan bo'sh lug'at yarating. Keyin har bir ro'yxatning har bir harfini pastadir. Yangi tugma va qiymati = 1 bo'lsa, xat hali tugmachada yakuniy bo'lmasa. Aks holda, ushbu kalit uchun 1 qiymatini qo'shing.

2
qo'shib qo'ydi
Python
Python
372 ishtirokchilar

Bu guruh python dasturlash tilini muhokama qilish uchun. Iltimos, o'zingizni hurmat qiling va faqat dasturlash bo'yicha yozing. Botlar mavzusini @botlarhaqida guruhida muhokama qling! FAQ: @PyFAQ Offtopic: @python_uz_offtopic

Python offtopic group !
Python offtopic group !
150 ishtirokchilar

@python_uz gruppasining offtop gruppasi. offtop bo'lsa ham reklama mumkin emas ) Boshqa dasturlash tiliga oid gruppalar @languages_programming