วิธีแก้ปัญหาแบร์โบน
เริ่มจากวิธีง่ายๆในการพิมพ์ลำดับของ มันไม่ได้เกี่ยวข้องกับข้อมูลเฉพาะที่คุณเพิ่มลงในคำถาม แต่เป็นจุดเริ่มต้นที่ดี:
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)
}