Thursday, January 17, 2013

Tcl ցուցակների հետ աշխատանքը

Ցուցակները Tcl լեզվում կառուցվում են list պրոցեդուրայով։ Այն ստանում է արգումենտների ցուցակ, հաշվարկում է դրանք և արդյունքներից կառուցվում է նոր ցուցակ։ Օրինակ,
set a [list [expr 1 + 2] 7 [expr 34 * 2]]
պրոցեդուրայի կատարումը a փոփոխականին կվերագրի {3 7 68} ցուցակը։ Հաստատուններից ցուցակ կարելի է կառուցել դրանք պարզապես թվարկելով "{" և "}" փախագծերի միջև։ Օրինակ,
set b {1 2 3 4 5}
Ցուցակի ամեն մի տարրն իր հերթին կարող է լինել ցուցակ։ Այդպիսին է օրինակ {a b c {3 4} d {5 6}} ցուցակը, որի տարրերից երկուսը ցուցակներ են։

Որևէ տողից կարելի է ցուցակ ստանալ, այն կտրտելով տրված բաժանիչով։ Օրինակ, եթե տրված է "a,b,c,d" տողը, ապա նրանից {a b c d} ցուցակը կարող ենք ստանալ ահա այսպես.
set c [split "a,b,c,d" ,]
Իսկ եթե տողում բաժանիչները մի քանիսն են, օրինակ ինչպես "a,b:c;d" տողում, ապա նույն {a b c d} ցուցակը կարելի է ստանալ split պրոցեդուրայի երկրորդ արգումենտում տալով բոլոր բաժանիչները.
set c [split "a,b,c,d" ",:;"]
split պրոցեդուրայի հակառակ գործողությունն է կատարում join պրոցեդուրան, որը տրված ցուցակի տարրերը տարրերը միացնում է իրար և ստանում տող՝ տարրի միջև ավելացնելով տրված տողը։ Օրինակ, {1 2 3 4} ցուցակից "1 + 2 + 3 + 4" տողը ստանալու համար կարող ենք գրել
set d [join {1 2 3 4} { + }]
Մի քանի ցուցակներ իրար կցելու և նոր ցուցակ ստանալու համար է նախատեսված concat պրոցեդուրան։ Օրինակ, {6 7 8 9}, {g h i j} և {"a 1" "b 2" "c 3"} ցուցակներից մի նոր ցուցակ կարող ենք ստանալ՝ կատարելով հետևյալ հրամանը.
set e [concat {6 7 8 9} {g h i j} {"a 1" "b 2" "c 3"}]
կատարման արդյունքում կստացվի {6 7 8 9 g h i j "a 1" "b 2" "c 3"} ցուցակը։

Ցուցակ կարելի է կազմել նաև տրված տարրը lrepeat պրոցեդուրայի օգնությամբ տրված քանակով կրկնելով։ Օրինակ, եթե ուզում ենք կառուցել տաս z տառերից բաղկացած ցուցակ, ապա պետք է գրել.
set u [lrepeat 10 z]
Տրված ցուցակի պոչից նոր տարր կցելու համար lappend պրոցեդուրայի առաջին արդումենտում պետք է տալ այն ցուցակը, որին ուզում ենք կցել տարրերը, իսկ հաջորդ արգումենտներով՝ կցվող տարրերը։ Օրինակ,
set a [list 1 2 3]
lappend a 4 5 6
Առաջին տողը կատարվելիս a փոփոխականի վերագրվում է {1 2 3} ցուցակը։ Հաջորդ տողը կատարելիս արդեն a-ն փոխվում է՝ ստանալով {1 2 3 4 5 6} արժեքը։ lappend պրոցեդուրան փոխում է իր առաջին արգումենտում տրված ցուցակը, բայց նաև վերադարձնում է նոր ստեղծված ցուցակը։

Ցուցակի տարրերի միջև նոր տարրեր խցկելու համար պետք է օգտագործել linsert պրոցեդուրան։ Նրա առաջին արգումենտը ցուցակն է, որում պետք է խցկել նոր տարրեր, երկրորդը ինդեքս է՝ այն տարրի ինդեքսը, որից առաջ պետք է խցկել տարրերը, հաջորդ արգումենտներով արդեն տրվում են ավելացվող տարրերը։ Օրինակ, եթե {1 2 3} ցուցակի սկզբից 8 և 9 տարրերն ավելացնելու համար ինդեքսը պետք է տալ զրո.
linsert {1 2 3} 0 8 9
Այս հրամանը կվերադարձնի {8 9 1 2 3} ցուցակը։ Իսկ {1 8 9 2 3} ցուցակը ստանալու համար պետք է գրել հետևյալը.
linsert {1 2 3} 1 8 9
Ցուցակի վերջից տարրերն ավելացնելու համար (մոտավորապես այնպես, ինչպես անում է lappend պրոցեդուրան) ինդեքսի փոխարեն պետք է տալ end բառը.
linsert {1 2 3} end 8 9
Ցուցակի տարրերը հեռացնելու կամ այլ տարրերով փոխարինելու համար է նախատեսված lreplace պրոցեդուրան։ Այն առաջին արգումենտում ստանում է ցուցակը, որի տարրերը պետք է փոխարինել, երկրորդ և երրորդ արգումենտով ստանում է փոխարինվող տարրերի միջակայքի ինդեքսները, իսկ հաջորդ արգումենտներով ստանում է այն տարրերը, որոնք պետք է տեղադրվեն հեռացվածների փոխարեն։ Օրինակ, {1 2 3 4 5 6 7} ցուցակից {1 2 a b c d 6 7} ցուցակը ստանալու համար պետք է գրել.
lreplace {1 2 3 4 5 6 7} 2 4 a b c d
Նույն այդ ցուցակի վերջին երկու տարրերը հեռացնելու համար էլ պետք է գրել.
lreplace {1 2 3 4 5 6 7} end-2 end
Ցուցակի տարրերից որևէ մեկի արժեքը մեկ այլ արժեքով փոխարինելու համար պետք է lset պրոցեդուրային տալ ցուցակը ներկայացնող փոփոխականի անունը, տարրի ինդեքսը և նոր արժեքը։ Օրինակ, եթե a փոփոխականին վերագրված է {1.2 3.4 5.6 7.8 9.0} ցուցակը, և ուզում ենք 7.8 արժեքը փոխարինել 8.7 արժեքով, ապա կարող ենք գրել.
set a {1.2 3.4 5.6 7.8 9.0}
lset a 3 8.7
lset պրոցեդուրայով կարելի է փոփոխել նաև ներդրված ցուցակների տարրերը։ Այս դեպքում ինդեքսի փոխարեն պետք է տալ ինդեքսների ցուցակ։ Օրինակ, եթե b փոփոխականին վերագրված է {{x0 1.2} {x1 3.4} {x2 5.6} {x3 7.8} {x4 9.0}} ցուցակը, և մեզ պետք է 5.6 արժեքը փոխարինել 0.0 արժեքով, ապա կարող ենք գրել.
set b {{x0 1.2} {x1 3.4} {x2 5.6} {x3 7.8} {x4 9.0}}
lset b {2 1} 0.0
Եթե պետք է ստանալ ցուցակի տրված ինդեքսով տարրը, ապա lindex պրոցեդուրային պետք է տալ ցուցակը և պահանջվող տարրի ինդեքսը։ (Եթե որևէ ինդեքս տրված չէ, ապա այս պրոցեդուրան վերադարձնում է ամբողջ ցուցակը։) Օրինակ, հետևյալ արտահայտությունը k փոփոխականին վերագրում է {x1 3.4}.
# set b {{x0 1.2} {x1 3.4} {x2 5.6} {x3 7.8} {x4 9.0}}
set k [lindex $b 1]
Եթե հարկավոր է k փոփոխականին վերագրել 3.4 արժեքը, ապա ինդեքսի փոխարեն պետք է տալ ինդեքսների ցուցակ (ինչպես lset պրոցեդուրայի դեպքում).
set k [lindex $b {1 1}]
Մի տարրի փոխարեն ցուցակի տարրերի տրված ինդեքստներով սահմանափակված հատվածը կարելի է ստանալ lrange պրոցեդուրայով։ Այն ստանում է ցուցակը, պահանջվող հատվածի սկզբի և վերջի ինդեքսները. ընդ որում, վերջին ինդեքսով որոշվող տարրը արդյուքի մեջ չի ներառվում։ Օրինակ, {a b c d e f g h} ցուցակից def բառը ստանալու համար պետք է գրել.
join [lrange {a b c d e f g h} 3 5] {}
Ցուցակում տրված շաբլոնին համապատասխանող տարրի առկայությունը որոշելու համար է նախատեսված lsearch պրոցեդուրան։ Սա վերադարձնում է որոնվող տարրի ինդեքսը, կամ -1 արժեքը՝ եթե որոնումն անհաջող է ավարտվել։ Օրինակ, ենթադրենք, թե a փոփոխականին վերագրված է {1.2 3.4 5.6 7.8 3.4 9.0} ցուցակը։ 7.8 արժեքով տարրի ինդեքսը որոշելու համար պետք է գրել.
set k [lsearch -real $a 7.8]
որտեղ -real բանալին ցույց է տալիս, որ որոնման ժամանակ արժեքները համեմատվելու են որպես իրական թվեր։ Ցուցակը 3.4 արժեքը պարունակում է երկու անգամ և այդ երկու տարրերի ինդեքսները որոշելու համար lsearch պրոցեդուրայի կանչի ժամանակ պետք է տալ -all բանալին, և այս դեպքում կստանանք ինդեքսների ցուցակ։
set k [lsearch -real -all $a 3.4]
Այժմ ենթադրենք, թե b փոփոխականի հետ կապված է {c7 b4 a0 B6 a2 c8 a1 b3 B5} ցուցակը, և ուզում ենք ստանալ այն տարրերը, որոնց սկսվում են a տառով։
puts [lsearch -ascii -all -inline -regexp $b {^a}]
Այս արտահայտության մեջ -ascii բանալին նշում է, որ ցուցակի տարրերը տողեր են, -inline բանալին ցույց է տալիս, որ պետք է վերադարձնել ոչ թե տառերը, այլ գտնված տարրերը։ -regexp բանալին ասում է, որ որոնման ժամանակ տարրերը պետք է համապատասխանեմ տրված կանոնավոր արտահայտությանը, իսկ {^a} արտահայտությունը ճանաչում է բոլոր այն տարրերը, որոնց առաջին տարրը a է։ Եթե հարկավոր է, որ որոնում կատարելիս անտեսվեն մեծատառերի ու փոքրատառերի տարբերությունները, ապա պետք է գրել նաև -nocase բանալին։

Ցուցակները կարդավորելու (sort) համար է lsort պրոցեդուրան: Օրինակ, նախորդ b ցուցակը այբբենական եղանակով կարգավորելու համար պետք է գրել.
puts [lsort -nocase -ascii $b]
Նույն ցուցակը հակառակ կարգով կարգավորելու համար հրամանին պետք է ավելացնել -decreasing բանալին։ Եթե հարկավոր է կարգավորման ժամանակ ցուցակից հեռացնել կրկնությունները, ապա պետք է տալ նաև -unique բանալին։

Ցուցակը շրջելու համար պետք է օգտագործել lreverse պրոցեդուրան: Այն ստանում է ցուցակը և վերադարձնում է մեկ այլ ցուցակ, որում նախնականի տարրերն են՝ թվարկված հակառակ հաջորդականությամբ։ llength պրոցեդուրան պարզապես վերադարձնում է տրված ցուցակի տարրերի քանակը։

No comments:

Post a Comment