Liste içinde en çok geçen eleman

merhaba arkadaşlar şöyle bir listem var mesela

liste =["elma","armut","elma","kiraz","karpuz","Üzüm","elma","elma"]

bu listede en çook geçen kaç defa geçmiş onu buldurabiliyorum fakat en çok hangisi geçmiş ve kaç adet bunu yazdıramadım yardımcı olabilecek var mı

Bunu nasil yapiyorsun?

liste =["elma","armut","elma","kiraz","karpuz","Üzüm","elma","elma"]
listee = []
for i in liste:
    listee.append(liste.count(i))
print(max(listee))

kodum şuan bu şekilde

listee'ye eleman sayisi yerine (eleman sayisi, eleman) ikilisini alabilirsin:

listee.append((liste.count(i), i))

max'in da buna gore calismasi lazim—ki calisiyor, ikililere bakarken once ilk elemani, sonra ikinci elemani hesaba katiyor.

tamamdır hallettim programı teşekkür ederim ilgilendiğin için

Ignoring exception in on_message
Traceback (most recent call last):
  File "C:\Users\Python\lib\site-packages\discord\client.py", line 270, in _run_event
    await coro(*args, **kwargs)
  File "C:\Users\cagla\OneDrive\Masaüstü\discord\sadfecadsfdfs.py", line 20, in on_message
    if word not in wordcount:
TypeError: unhashable type: 'list'

şimdi de bu hatayı alıyorum :frowning:

Hata sadfecadsfdfs.py'de.

1 Beğeni

zaten tek o dosya var biliyorum onda olduğunu

listem bu şekilde acaba o yüzden mi

[[‘öğe1’], [‘öğe2’]]

Böyle yaparsa tek elman dönecek strleride alfabetik sıraladığı için ama arkadaş en çok tekrar edenlerin hepsini belirlemeye çalışıyor galiba onun için 1.ci elemanı max a eşit olanları çekip alsa daha iyi olmazmı

Önce liste içindeki listelerden kurtulabilirsiniz. Daha sonra da her bir elemanın listede kaç defa geçtiğini ve bu elemanın hangi eleman olduğunu bulan bir fonksiyon yazabilirsiniz.

#!/usr/bin/python3.8
# -*- coding: utf-8 -*-

# İç içe geçmiş listelerden kurtaran fonksiyon
unnest = lambda x: [
    *map(
        lambda i: "".join((unnest(i))) 
        if isinstance(i, list) else i, x
    )
]

# Listede en çok geçen elemanları bulan fonksiyon
find_max = lambda x: [
    *filter(
        lambda i: i, map(
            lambda j: {j: y[j]} if y[j] == max(y.values()) else [], 
            (y := {k: x.count(k) for k in x})
        )
    )
]

Örnek:

liste = [
    ["elma"], 
    ["armut"], 
    ["elma"], 
    ["kiraz"], 
    ["karpuz"], 
    ["Üzüm"], 
    ["elma"], 
    ["elma"]
]

print(find_max(unnest(liste)))

Çıktı:

[{'elma': 4}]

Şöyle de yapabilirsiniz, ama benim pek hoşuma gitmedi.

#!/usr/bin/python3.8
# -*- coding: utf-8 -*-

find_max = lambda x: [
    *filter(
        lambda i: i[1] == max([j[1] for j in y]), 
        (y := [[i, x.count(i)] for i in x])
    )
]
liste = [
    ["elma"], 
    ["armut"], 
    ["elma"], 
    ["kiraz"], 
    ["karpuz"], 
    ["Üzüm"], 
    ["elma"], 
    ["elma"]
]

print(find_max(liste))
[[['elma'], 4], [['elma'], 4], [['elma'], 4], [['elma'], 4]]

Cunku aslinda butun isi max([j[1] for j in y]) bir kerede yapiyor, bunu her eleman icin tekrar tekrar calistirmak cirkin.

let expression’lari olsaydi let max_num = max(...) in filter(λe: e[1] == max_num) derdik ama yok.

:= de side effect habercisi, filter/lambda gibi functional programming construct’larinin yanlis olabilecegine isaret ediyor.

Bunun fonksiyonel cozumu listeyi [(eleman, sayisi)] ciftlerine fold (reduce) edip—diyordum ki y’nin bu oldugunu fark ettim. O zaman y’yi sort edip ilk/son elemani dondursek olmuyor mu?

Aynen öyle. :+1:

Şöyle bir çözüm yolu geldi aklıma:

find_max = lambda x: [
    *map(
        lambda m: [[[*m][0][2:-2]], m[1]], set(
            filter(
                lambda i: i[1] == max([j[1] for j in y]),
                (y := [(str(k), x.count(k)) for k in x])
            )
        )
    )
]

Örnek:

liste = [
    ["elma"],
    ["armut"],
    ["armut"],
    ["armut"],
    ["elma"],
    ["armut"],
    ["elma"],
    ["kiraz"],
    ["kiraz"],
    ["kiraz"],
    ["kiraz"],
    ["üzüm"],
    ["şeftali"],
    ["karpuz"],
    ["elma"]
]
print(find_max(liste))

Çıktı:

[[['elma'], 4], [['armut'], 4], [['kiraz'], 4]]

Burada ilk oluşturulan listede aynı elemanlar için i[1] == max([j[1] for j in y]) ifadesi bir çok kez çalışıyor. (y := [(str(k), x.count(k)) for k in x]) ifadesiyle, aslında set için kullanılabilir bir veri oluşturuyoruz. set’i oluşturduktan sonra gerisi veri manipülasyonu.

sort edip ilk ve son elemanı geri döndürmeyi düşündüm ama ya listede en çok geçen veriler 2’den fazlaysa? 1 veya 2 tane veri için bu kullanışlı bir yöntem olabilir ama 3. bir veri de listede en çok geçen veri olursa, o zaman bu yöntem istediğimiz gibi çalışmaz herhalde. Bilmiyorum siz ne düşünüyorsunuz?

Su biraz basimi agritti :tired_face:

Calistirip da bakamiyorum ne yaptigina, Python 3.7 var. Aklimda daha cok soyle bir sey vardi:

import functools

liste = [
    "elma", "armut", "armut", "armut", "elma", "armut", "elma", "kiraz",
    "kiraz", "kiraz", "kiraz", "kiraz", "üzüm", "şeftali", "karpuz", "elma"
]

dict_merge = lambda a, b: {**a, **b}

counts = functools.reduce(
    lambda counts, e: dict_merge(counts, {e: counts[e]+1 if e in counts else 1}),
    liste,
    {}
)
print(counts)
counts_sorted = sorted(counts.items(), key=lambda k_v: k_v[1], reverse=True)
print(counts_sorted[0])

Bunun ne yaptigi hakkinda hic bir fikrim yok :frowning: 2, -2 indisleri nereden geliyor?

Verilen nesneyi iterate ediyor, gerçi bunu mu kastettiniz emin değilim:

>>> a = "abcd"
>>> [*a]
['a', 'b', 'c', 'd']
>>> list(a)
['a', 'b', 'c', 'd']
>>> {*a}
{'b', 'a', 'd', 'c'}
>>> set(a)
{'b', 'a', 'd', 'c'}
>>> [i for i in a]
['a', 'b', 'c', 'd']
>>> {i for i in a}
{'b', 'a', 'd', 'c'}

Gibi.

[*x]'in ne yaptigina acip bakabilirim de [*map(lambda m: [*m][0][2:-2], ...)] ne yapar bilmiyorum, ki yukaridaki expression da daha karisik.

Son zamanlarda list(m) veya list(map(...)) kullanmam gereken yerlerde kısa olsun diye şöyle yazıyorum [*m] veya [*map(...)].

İsterseniz fonksiyonu biraz parçalayayım.

Mesela o kısmı kaldırdım:

find_max = lambda x: set(
    filter(
        lambda i: i[1] == max([j[1] for j in y]),
        (y := [(str(k), x.count(k)) for k in x])
    )
)

Bu yukarıdaki kodlarla alacağımız çıktı şöyle olacak:

{("['armut']", 4), ("['elma']", 4), ("['kiraz']", 4)}

Hash hatasından kurtulmak için dıştaki listeyi bir tuple’a, içteki listeyi de bir str’ verisine çevirdim:

(str(k), x.count(k))

Aşağıdaki kod ile de str verisini belli indislerinden aldım tekrar liste haline getirdim ve m[1] ile birlikte daha büyük bir listeye dahil ettim.

lambda m: [[[*m][0][2:-2]], m[1]], set(...)

Sonuç olarak şöyle bir çıktı aldım:

[[['elma'], 4], [['armut'], 4], [['kiraz'], 4]]

Mesela o kısmı şöyle yazsaydım:

find_max = lambda x: [
    *map(
        lambda m: [m[0], m[1]], set(
            filter(
                lambda i: i[1] == max([j[1] for j in y]),
                (y := [(str(k), x.count(k)) for k in x])
            )
        )
    )
]

Alacağımız çıktı şöyle olacaktı:

[["['elma']", 4], ["['armut']", 4], ["['kiraz']", 4]]

Dolayısıyla [[[*m][0][2:-2]], m[1]] ifadesi yukarıdaki sonucu [[['elma'], 4], [['armut'], 4], [['kiraz'], 4]] şeklinde almamızı sağlıyor.

Özet olarak, list içinde list ve bunun da içinde str verisi olunca aşağıdaki fonksiyon orijinal veriyi bozmadan sonucu çıkartıyor.

#!/usr/bin/python3.8
# -*- coding: utf-8 -*-

find_max = lambda x: [
    *map(
        lambda m: ([[*m][0][2:-2]], m[1]), set(
            filter(
                lambda i: i[1] == max([j[1] for j in y]),
                (y := [(str(k), x.count(k)) for k in x])
            )
        )
    )
]

liste = [
    ["elma"], ["armut"], ["armut"], ["armut"], ["elma"], ["armut"],
    ["armut"], ["elma"], ["kiraz"], ["kiraz"], ["kiraz"], ["elma"],
    ["kiraz"], ["kiraz"], ["üzüm"], ["şeftali"], ["karpuz"], ["elma"]
]
  
print(find_max(liste))

Çıktı:

[(['kiraz'], 5), (['elma'], 5), (['armut'], 5)]

Ama list içinde sadece str varsa yukarıdaki yöntemin yerine ilk mesajımda belirttiğim yöntem kullanılabilir:

#!/usr/bin/python3.8
# -*- coding: utf-8 -*-

find_max = lambda x: [
    *filter(
        lambda i: i, map(
            lambda j: (j, y[j]) if y[j] == max(y.values()) else [], 
            (y := {k: x.count(k) for k in x})
        )
    )
]

liste = [
    "elma", "armut", "armut", "armut", "elma", "armut",
    "armut", "elma", "kiraz", "kiraz", "kiraz", "elma",
    "kiraz", "kiraz", "üzüm", "şeftali", "karpuz", "elma"
] 

print(find_max(liste))

Çıktı:

[('elma', 5), ('armut', 5), ('kiraz', 5)]

Sizin paylaştığınız kodlarda 0. indis değerindeki elemanı sorted yaparak alıyorsunuz, ama liste içinde "elma" ve "kiraz" stringleri aynı sayıda geçmişse o zaman bu yöntemi biraz değiştirmek gerekir.

Not: Bu arada Python3.8’de iyiki Walrus Operatörü özelliğini getirmişler.

Ah, tamam.

Ama str(k[0]) desek daha kolay olmaz miydi?