Stringi Operatöre çevirme

Merhaba. [ 1 , “+” , 3 ] diye bir liste oluşturduğumuzu varsayalim. Listedeki “+” karakterini + operatorüne nasıl çevirebilirim.

Detaylı kullanımına buradan bakabilirsiniz : operator — Standard operators as functions — Python 3.9.2 documentation

import operator

liste = [ 1 , "+" , 3 ]

arti = {liste[1]: operator.add}

print(arti[liste[1]](liste[0],liste[2]))

Bu çözümü denedim. Eval ve koşul ifadeleriyle de denedim ancak bunlar geçici çözüm ve sadece belirli olasılıklarda kullanılıyor. Benim istediğim operatoru değişken vasıtası ile kullanmak ya da string değeri operatöre çevirmek.

eval(list(map(lambda x: str(x), [1, "+", 4])))

Dostlar daha önce EVAL, OPERATOR ADD ve SPLİT (koşul ile) benzeri ifadelerle yaptım çözüme ulaştırdı ama bunlar sadece GEÇİCİ ÇÖZÜM. String bir operator ifadesini tekrar operator işlevi ile nasıl kullanacağımı merak ediyorum ben.

Sunulan cevaplardaki eksikleri söyler ve örnek sayısını arttırırsanız daha rahat yardım ederiz. Çözümlerin geçici olduğunu söylemeniz, çözümün eksikleri hakkında pek bir şey ifade etmiyor.

1 Beğeni

[ " 1 ", " - ", " 2 ", " * ", " 9 " ] şu şekilde bir liste olduğunu varsayalim. Bu listeyi ( 1 - 2 * 9 ) şeklinde matematik işlemi yapıp çözüme ulamşaya çalışalım. Operator.add kullanimi burada sinifta kalıyo. Parçalara ayirip ikili şekilde çözüm üretmesi gerekiyo. Eval kullanırsak sonuca ulaşıyoruz ancak verilen problem 4 işlemden fazlasini içerirse eval yetersiz kalıyo ki eval çok da güvenilir bir fonksiyon değil. Split ile parçalara ayirip, işlem önceliğine uygun fonksiyonlar tanimlayıp liste içersinde dönerek sonuca ulaşılabilir. Ancak bu da uzun ve karmaşık bir yapı oluşturuyor. Benim sorun listedeki “+” karakteri + operatorune cevrilebilir mi? Ya da değişkene atanabilir mi ? Ya da herhangi bir kısa yol… Yani yukardaki listeden gidecek olursak koşul yapisi içersinde “+” karakterini gördüğü zaman o kısma + operatörü eklemenin bir yolu var mı? İngilizce araştırdım ancak pythonda bulamadım. Java ile ilgili bir kaç forumda rastladım bu başlığa ama onlar da yeterli bilgiyi sağlayamamıştı.

import operator

ops = { '+': operator.add }
xs = [1 , '+' , 3]
ys = [ops.get(e, e) for e in before]

Problemin ne oldugunu soylemezsen hangi cozumlerin gecici oldugunu muhakeme edemeyiz.

Bu uzun ve karmasik yapiyi gosterirsen basitlestirebilen birinin cikacagini tahmin ediyorum.

Sorumu tam olarak anlatamadığım için karmaşık diye bahsettiğim kodlari yazdim. Sırayla matematik operatorlerini bulup işlem önceliğine uyarak sonuçları yapıp her defasında listeyi duzenledim. Videoda işlemi algılayan ve yanina çözümü yazan bir program. Tesseract kullaniminda zaten elimizde liste oluşuyo. Örnek olarak [ “5” , “*” , “7” , “-” , “6” , “/”, “3”, “=”] şöyle bir liste oluşuyo. Eğer matematiksel operatörler değişkene tanimlanabilseydi basit bir koşul ifadesi ile 5 satirda sorunu çözmüş olurduk. Yani liste[1] = * sonra çarpma işlemini kullanip islemi tek satirda yaptirmak gibi. Ancak uzun çözümde yani yaptığım çözümde her işlem sirayla aranip parçalara ayrilip sırayla çözlüyo ve her defasında liste tekrar tanimlaniyo.
not: kod bloklarinda girinteleme hatasi olabilir, kopyala yapıştır yapınca duzenli sekilde yapiştirilmadi elle duzelttim.

import cv2
from PIL import Image
import pytesseract

cap = cv2.VideoCapture(r"C:\Users*******\video.mp4")

file_name = r"C:\Users**************\video.avi"
codec = cv2.VideoWriter_fourcc(“W”, “M”, “V”, “2”)
frame_rate = 30
resolution = (840, 510)
video_save = cv2.VideoWriter(file_name, codec, frame_rate, resolution)

while True:
    ret, frame = cap.read()
    if ret == 0:
        break

    cv2.imwrite(r"C:\Users\*****************\write_img.jpg", frame)
    img = Image.open(r"C:\Users\**************\write_img.jpg")
    text = pytesseract.image_to_boxes(img, lang="eng")

    text = text.split("\n")

    try:
        bos_index = text.index("")
        text.pop(bos_index)
    except Exception:
        pass

    x_index_list = []
    y_index_list = []
    liste = []

    for i in text:
        i = i.split(" ")
        liste.append(i[0])
        x_index_list.append((i[1], i[2]))
        y_index_list.append((i[3], i[4]))

    try:
        basamak = []
        p = 0
        sayi = 0
        for i in range(len(liste) * 3):    # GELİSTİRİLMESİ LAZIM 

            try:
                liste[p] = int(liste[p])
                basamak.append((p, liste[p]))

            except:
                m = 0
                if len(basamak) >= 2:

                    for i in range(len(basamak)):
                        sayi = str(sayi) + str(basamak[i][1])

                    for i in range(len(basamak)):
                        liste.pop(basamak[0][0])

                    liste.insert(basamak[0][0], int(sayi[1:]))
                    basamak.clear()
                    sayi = 0
                    p = 0
                    continue

                elif len(basamak) < 2:
                    basamak.clear()

            p = p + 1

        soa = int(x_index_list[0][0]), row - int(x_index_list[0][1])
        soa2 = int(x_index_list[1][0]), row - int(x_index_list[1][1])
        soason = int(x_index_list[-2][0]), row - int(x_index_list[-2][1])

        sayilar_arasi_uzaklik = soa2[0] - soa[0]
        yeni_bolge = (soason[0] + int(sayilar_arasi_uzaklik * 2.2), soason[1])

        esit_index = liste.index("=")
        liste = liste[:esit_index]
        liste_cb = []
        liste_ct = []


        def listele():
            z = 0
            global liste_cb
            global liste

            for i in liste:

                if i == "*" or i == "/":

                    if i == "*":
                        liste_cb.append(("*", z))

                    elif i == "/":
                        liste_cb.append(("/", z))
                z = z + 1

            return liste_cb


        def listele2():
            k = 0
            global liste_ct
            global liste

            for i in liste:

                if i == "+" or i == "-":

                    if i == "+":
                        liste_ct.append(("+", k))

                    elif i == "-":
                        liste_ct.append(("-", k))
                k = k + 1

            return liste_ct


        listele()

        if liste_cb is not None:

            for r in range(len(liste_cb)):
                i = liste_cb[0]

                if i[0] == "*":
                    islem1 = int(liste[i[1] - 1]) * int(liste[i[1] + 1])
                    liste[i[1] - 1] = islem1
                    liste.pop(i[1] + 1)
                    liste.pop(i[1])
                    liste_cb.pop(0)
                    liste_cb.clear()
                    listele()

                elif i[0] == "/":
                    islem2 = int(liste[i[1] - 1]) / int(liste[int(i[1]) + 1])
                    liste[i[1] - 1] = islem2
                    liste.pop(i[1] + 1)
                    liste.pop(i[1])
                    liste_cb.pop(0)
                    liste_cb.clear()
                    listele()

        listele2()

        if liste_ct is not None:

            for q in range(len(liste_ct)):
                i = liste_ct[0]

                if i[0] == "+":
                    islem3 = int(liste[i[1] - 1]) + int(liste[i[1] + 1])
                    liste[i[1] - 1] = islem3
                    liste.pop(i[1] + 1)
                    liste.pop(i[1])
                    liste_ct.pop(0)
                    liste_ct.clear()
                    listele2()

                elif i[0] == "-":
                    islem4 = int(liste[i[1] - 1]) - int(liste[int(i[1]) + 1])
                    liste[i[1] - 1] = islem4
                    liste.pop(i[1] + 1)
                    liste.pop(i[1])
                    liste_ct.pop(0)
                    liste_ct.clear()
                    listele2()

        if sayilar_arasi_uzaklik < 10:
            font_buyukluk = 1
        elif sayilar_arasi_uzaklik < 35 and sayilar_arasi_uzaklik > 10:
            font_buyukluk = 2
        elif sayilar_arasi_uzaklik < 55 and sayilar_arasi_uzaklik > 35:
            font_buyukluk = 3
        elif sayilar_arasi_uzaklik < 85 and sayilar_arasi_uzaklik > 55:
            font_buyukluk = 4
        elif sayilar_arasi_uzaklik > 85:
            font_buyukluk = 5
        else:
            font_buyukluk = 6

        cv2.putText(frame, f"{liste[0]}", yeni_bolge, cv2.FONT_HERSHEY_SIMPLEX, font_buyukluk, (0, 0, 255), 5)

    except:
        print("bulamadi")

    cv2.imshow("frame", frame)
    video_save.write(frame)

    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()paragraf girintisi 4 boşluktan oluşan, önceden biçimlendirilen yazı

Kod bir takim vidyo dosyalari olmadan calismiyor, o yuzden okuyabildigim kadariyla yaziyorum:

  • Her operator icin birbirinin ayni bir kod blogu yazmissin. Normalde bu durumda bir fonksiyon veya dongu kullanimi tercih ediliyor.
  • Fonksiyon yazmisken vidyo isleyen kisimla denklem degerlendiren kismi ayirmak isteyebilirsin.
  • Operatorler ve oncelik siralari kod akisiyla belirlenmis. Oysa kodun icinde data ile belirlenmeliydi (bir listedeki siralarina veya yanlarindaki bir sayinin buyuklugune gore mesela.)
  • listele ve listele2 ayni isme sahip olduklari halde farkli isler yapiyorlar.

Yapmaya calistigin seyin genel adi parsing. Operatorlerin (islec) arity (parametre sayisi), precedence (oncelik) ve associativity niteliklerine gore tanimlanan islemi calistirmaya calisiyorsun. Basit expression parser’larin nasil calistiklarina bakabilirsin. Anti-parantez: Veya ifadeyi infix’ten prefix veya postfix yazilma sekline cevirecek bir cozum kullanabilirsin. Precedence ve associativity cevrim adimlarinda kullanilip bir daha karsina cikmiyorlar. Prefix veya postfix notasyondaki bir ifadeyi calistirmak cok kolay.

Bunun nasil yapildigini yukarida gosterdim.

operator.mul. Fakat sonra islemi tek satirda nasil yaptirabilecegini dusundugunu anlamadim. Islem onceligi olmasaydi belki. Prefix veya postfix olsaydi tamam.

2 Beğeni

Kodları sadece aklımdaki soruya çözüm almak için baştan salma yazdım, fonksiyon isimlerine aldırış etmeden, nesne tabanlı programlamaya girmeden, tek dosyada her şeyi sizlere göstermek istedim. Bu yüzden eksikleri fazla. Web Scraping yaparken parsing ile mecbur uğraşıyodum zaten, az çok aşinayım. İnfix, prefix, postifxi daha geçen dönem derste gördük ama hiç dikkatle bakmamıştım. Sanırım artık her bilgiye olumlu yaklaşmanın vakti gelmiş :smile: . Dediklerinizi deneyecem. Teşekkür ederim.

Web scraping yaparken oteki taraftan kullaniliyor aslinda—ifadeyi (XML/JSON dokumanini) agaca ceviren kutuphane hazir, sen agacta yuruyorsun. Burada agaci da sen olusturuyorsun, islem onceligi gibi kurallari kullanarak. (Bu arada bu agac bir abstract syntax tree sayilabilir, arastirmak istersen.)

Bu arada python parser kutuphanelerinin herhangi bir tanesini de kullanabilirsin. Hangisi en basidi bilmiyorum malesef (ve inan bana, en basidini kullanmak istersin :​) Parser siniflandirmalarindan anlayan varsa soylesin (hatta soyle ozet gecse ne guzel olur.)

Notasyonlarla maalesef yapamadım. Şimdilik yoğunluğumdan dolayı yarıda bırakmak zorunda kalıyorum. Son halini merak edenler için videoyu buraya bırakıyorum. Kaynak kod da yukarıda zaten.

https://www.youtube.com/watch?v=R1LFe_QoWsE