Friday, December 21, 2012

Python: Բառարանի օգտագործումը

Այս գրառման մեջ ես առաջարկում եմ ևս մի լուծում իմ նախորդ գրառման մեջ առաջարկված և Tcl լեզվով լուծված խնդրի համար։ Նորից հիշեցնեմ խնդրի ձևակերպումը.
Տրված է որևէ գեղարվեստական ստեղծագործության տեքստ։ Կազմել տեքստում հանդիպող բառերի հաճախության բառարան, որտեղ ամեն մի բառին համապատասխանեցված է տեքստում նրա հանդիպելու քանակը։ Հաշվել տեքստի առանձին բառերի քանակի հարաբերությունը բոլոր բառերի քանակին։ Արտածել տաս ամենաշատ օգտագործված բառերի խմբերը։ Արտածել տաս ամենաերկար բառերը և նրանց հանդիպելու քանակը։ Արտածել միայն մեկ անգամ հանդիպող բառերի ցուցակը։
Այս անգամ նույն խնդրի լուծումը տալիս եմ Python ծրագրավորման լեզվով։


Եվ այսպես, տեքստից մեզ չհետաքրքրող (բառ չձևավորող) սիմվոլները հեռացնելու համար օգտագործելու ենք կանոնավոր արտահայտությունների re մոդուլը։
import re
Դատարկ բառարանը ստեղծվում է dict դասի կոնստրուկտորի կանչով։
words = dict()
Տեքստը տող առ տող ֆայլից կարդալու և բառերի տրոհելու համար with հրամանով ստեղծենք կատարման կոնտեքստ, որում fin փոփոխականին կապված է open հրամանով կարդալու համար բացված տեքստային ֆայլը (Ջեկ Լոնդոն, "Մարտին Իդեն"): Կատարման կոնտեքստում for հրամանով իտերացիա կազմակերպենք ֆայլի տողերով։ re մոդուլի sub մեթոդը տրված տողում փոխարինում է տրված կանոնավոր արտահայտությամբ ճանաչված հատվածները մեկ այլ տրված տեքստով։ Փոխարինումից հետո տողի բոլոոր մեծատառերը lower մեթոդով դարձնենք փոքրատառեր ու split մեթոդով տողը կտրտենք բառերի։ if հրամանով ստուգենք որ բառի երկարությունը մեծ լինի մեկից։ Հաջորդ if հրամանով և not in գործողությամբ ստուգենք ընթացիկ բառի առկայությունը բառարանում. եթե այն բացակայում է, ապա ավելացնում ենք՝ հաշվիչի 0 սկզբնական արժեքով։ Հաջորդ քայլում պարզապես հերթական բառի հաշվիչն ավելացնում ենք մեկով։
with open('martin-eden-jack-london.txt') as fin:
  for line in fin:
    line = re.sub('[^a-zA-Z]+', ' ', line)
    for wr in line.lower().split(' '):
      if len(wr) > 1:
        if wr not in words:
          words[wr] = 0
        words[wr] += 1
len ֆունկցիան վերադարձնում է dict օբյեկտի գրառումների քանակը։ մեր դեպքում դա տեքտի իրարից տարբեր բառերի քանակն է։ sum ֆունկցիան վերադարձնում է ցուցակի տարրերի գումարը։ Այստեղ ցուցակը words բառարանի արժեքների ցուցակն է, որի տարրերի գումարը ստացվում է տեքստի բոլոր բառերի քանակը։ format մեթոդը կատարում է տողի ֆորմատավորում, այն նաև տեղադրում է տրված արժեքները տողի նշված տեղերում։
uniwords = len(words)
allwords = sum(words.values())
print('{0} / {1} = {2}'.format(uniwords, allwords, 1.0 * uniwords / allwords))
sorted ներդրված ֆունկցիան վերադարձնում է արգումենտում տրված ցուցակի ըստ աճման կարգավորված տարբերակը։ Եթե reverse անվանված արգումենտը տրված է True, ապա վերադարձնում է ըստ արժեքների նվազման կարգավորված ցուցակը։ dict օբյեկտի values մեթոդը վերադարձնում է բառարանի արժեքների ցուցակը։ Մյուս, items մեթոդը հնարավորություն է տալիս իտերացիա կազմակերպել բառարանի բանալի-արժեք զույգերով։ in գործողությունը ստուգում է տարրի պատկանելիությունը ցուցակին։
tenbignums = sorted(words.values(), reverse=True)[0:10]
for word, count in words.items():
  if count in tenbignums:
    print('{0} : {1}'.format(word, count))
sorted ֆունկցիան key անվանված արգումենտով ստանում է այն բնութագիրը, ըստ որի պետք է համեմատվեն ցուցակի տարրերը։ Այստեղ որպես բնութագիր տրված է մի անանուն ֆունկցիա՝ ստեղծված lambda արտահայտության օգնությամբ, որը վերադարձնում է արգումենտի չափը։ Այս կերպ կարողանում ենք բառարանի բանալիների ցուցակը, որը ստացվում է keys մեթոդով, կարգավորել ըստ տարրերի երկարության։
tenbigwords = sorted(words.keys(), key=lambda w: len(w), reverse=True)[0:10]
for wd in tenbigwords:
  print('{0} : {1}'.format(wd, words[wd]))
Եվ վերջապես, տեքստում միայն մեկ անգամ օգտագործված գրված է մի հետաքրքիր արտահայտություն։ Այն կարելի է կարդալ մոտավորապես այսպես. "անցնել բառարանի տարրերով և ցուցակ կազմել այն բանալիներից, որոնց համապատասխանեցված արժեքը հավասար է մեկի"։
onlyone = [wd for wd, cnt in words.items() if cnt == 1]
print(onlyone)
* * *
Որպես գաղտնիք նշեմ, որ, չնայած խնդրի լուծումը համապատասխանում է պահանջին, բայց, այնուամենայինիվ, պարունակում է որոշ թերություններ։

No comments:

Post a Comment