วิธีแก้ปัญหาแบร์โบน
เริ่มจากวิธีง่ายๆในการพิมพ์ลำดับของ มันไม่ได้เกี่ยวข้องกับข้อมูลเฉพาะที่คุณเพิ่มลงในคำถาม แต่เป็นจุดเริ่มต้นที่ดี:
sub seq-range-gist ( @seq ) {
my @pairs = @seq.pairs;
join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}
ซึ่งแตกต่างจาก.kv
ที่แปลง invocant ของตนลงในแบบฟอร์มkey1, value1, key2, value2, key3, value3, ...
, IE 6 องค์ประกอบถ้า invocant มันมี 3 องค์ประกอบ.pairs
แปลง invocant key1 => value1, key2 => value2, key3 => value3, ...
ของตนลงในแบบฟอร์ม
ฉันใช้.pairs
แทน.kv
บางส่วนเพราะมันหมายความว่าฉันสามารถใช้ใน».gist
ภายหลังในรหัสเพื่อให้ได้key1 => value1
จอแสดงผลที่ดีสำหรับแต่ละองค์ประกอบ เราจะแก้ไขด้านล่าง แต่นี่เป็นจุดเริ่มต้นที่ดี
.head
และ.tail
สายเป็นวิธีที่เป็นสำนวนในการสร้างรายการเล็ก ๆ ขององค์ประกอบ N แรกและครั้งสุดท้ายจากรายการ invocant (ให้มันไม่ขี้เกียจ; เพิ่มเติมเกี่ยวกับว่าในเดือนก)
รับโซลูชันเริ่มต้นนี้say seq-range-gist (0,1 ... Inf)[^10]
แสดง:
0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9
ถัดไปเราต้องการที่จะ "วางองค์ประกอบแรก ... จากผลลัพธ์ที่พิมพ์" say seq-range-gist (0,1 ... Inf)[1..9]
แสดงน่าเสียดาย:
0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9
เราต้องการให้ตัวเลขทางด้านซ้ายของ=>
เพื่อรักษาหมายเลขของลำดับเดิม ในการเปิดใช้งานสิ่งนี้เราแยกลำดับพื้นฐานออกจากช่วงที่เราต้องการแยกออกมา เราเพิ่มพารามิเตอร์ / อาร์กิวเมนต์ที่สอง@range
และผนวก[@range]
เข้ากับบรรทัดที่สองของ sub:
sub seq-range-gist ( @seq, @range ) {
my @pairs = @seq.pairs[@range];
ตอนนี้เราสามารถเขียนsay seq-range-gist (0,1 ... Inf), 1..9
เพื่อแสดง:
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
ในคำถามของคุณที่คุณใช้รูปแบบมากกว่าaINDEX = VALUE
INDEX => VALUE
ในการอนุญาตให้ปรับแต่งส่วนสำคัญเราได้เพิ่ม&gist
พารามิเตอร์ / อาร์กิวเมนต์ประจำตัวที่สามและเรียกใช้งานแทน.gist
วิธีการที่มีอยู่แล้ว:
sub seq-range-gist ( @seq, @range, :&gist ) {
my @pairs = @seq.pairs[@range];
join "\n", @pairs.head(3)».&gist, '...', @pairs.tail(2)».&gist
}
โปรดทราบว่าตอนนี้การเรียกใช้ "เมธอด" ในเนื้อความของseq-range-gist
ย่อยนั้น.&gist
ไม่ใช่.gist
อย่างไร ไวยากรณ์.&foo
จะเรียกย่อย &foo
(ซึ่งถูกเรียกโดยการเขียนเพียงโดยทั่วไปfoo
) ผ่าน invocant ทางด้านซ้ายของ.
เป็น$_
อาร์กิวเมนต์ย่อย
ยังทราบว่าฉันได้ทำพารามิเตอร์ชื่อหนึ่งโดยก่อนหน้านั้นด้วย&gist
:
ดังนั้นตอนนี้say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }
แสดง:
a1 = 1
a2 = 2
a3 = 3
...
a8 = 8
a9 = 9
การเพิ่มเงา
ส่วนที่เหลือของคำตอบนี้เป็นวัสดุโบนัสสำหรับผู้อ่านที่สนใจเรื่องโปแลนด์
say seq-range-gist (0, 1, 2, 3), ^3
แสดง:
0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2
อุ่ย และแม้ว่าจะมีคู่มากกว่าส่วนหัวและหางรวมกันดังนั้นอย่างน้อยเราก็ไม่ได้เส้นที่ซ้ำกันมันก็ยังคงไม่มีจุดหมายโดยใช้head, ..., tail
วิธีการเพื่อกำจัดองค์ประกอบเพียงหนึ่งหรือสองอย่าง มาเปลี่ยนคำสั่งสุดท้ายในเนื้อหาย่อยเพื่อกำจัดปัญหาเหล่านี้:
join "\n",
@pairs < $head + $tail + 3 # Of course, the 3 is a bit arbitrary
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
ถัดไปมันจะดีถ้าย่อยทำสิ่งที่มีประโยชน์ถ้าเรียกว่าไม่มีช่วงหรือส่วนสำคัญ เราสามารถแก้ไขได้โดยให้ค่าเริ่มต้น@range
และ&gist
พารามิเตอร์ที่เหมาะสม:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
ถ้า@seq
เป็นไม่ได้ ขี้เกียจแล้วเริ่มต้นที่เต็มรูปแบบของ@range
@seq
ถ้า@seq
เป็นอนันต์ (ซึ่งในกรณีนี้คือสันหลังยาว) แสดงว่าค่าเริ่มต้นสูงสุด 100ดี แต่ถ้าเกิดว่า@seq
ขี้เกียจ แต่ให้ผลน้อยกว่า 100 ค่าที่กำหนดล่ะ เพื่อให้ครอบคลุมกรณีนี้เราผนวก.grep: *.value.defined
กับ@pairs
ประกาศ:
my @pairs = @seq.pairs[@range].grep: *.value.defined;
การปรับปรุงอย่างง่ายอื่น ๆ จะเป็นพารามิเตอร์ส่วนหัวและส่วนท้ายที่นำไปสู่วิธีแก้ไขปัญหาขั้นสุดท้าย
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:$head = 3,
:$tail = 2,
:&gist = { .gist }
) {
my @pairs = @seq.pairs[@range].grep: *.value.defined;
join "\n",
@pairs <= $head + $tail + 2
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
}