วิธีที่ชัดเจนในการข้ามองค์ประกอบแรกในดัชนีที่ใช้สำหรับลูป


9

ฉันมีการวนรอบที่ฉันต้องข้ามองค์ประกอบแรกในอาร์เรย์ zero-based

ข้อใดแสดงถึงความตั้งใจของฉันอย่างชัดเจนมากขึ้น

for($i=1 ; $i < count(array) ; $i++){
    array[$i];
}

หรือ

for($i=0+1 ; $i < count(array) ; $i++){
    array[$i];
}

28
ไม่ใช่$i=2-1เป็นวิธีที่เหนือกว่า : /
yannis

7
ฉันอาจจะไปที่ตัวเลือกแรกและเพิ่มความคิดเห็นเพื่ออธิบายว่าทำไมองค์ประกอบแรกต้องถูกข้ามไป
Vincent Savard

3
ความชัดเจนคือสิ่งที่ฉันมุ่งหวังฉันแก้ไขคำถาม มีความชัดเจนหรือไม่?
Tomas Zubiri

10
การไม่ใช้ PHP เป็นวิธีที่เหนือกว่า
แมว

3
PHP มีโครงสร้างแบบ foreach หรือไม่? คุณสามารถทำforeach ($i in range(1, count))(สิ่งที่ดูเหมือนใน PHP) หรือสิ่งที่ชอบforeach ($item in array.skip(1))ซึ่งเป็นสิ่งที่คน C # จะทำ
usr

คำตอบ:


23

ฉันเกลียดทั้งคู่

ใครบอกว่าคุณสามารถใช้หมายเลขเวทย์มนตร์? หากคุณกำลังจะเริ่มต้นด้วยการชดเชย 1 วิธีบอกเราว่าทำไมคุณถึงเริ่มที่การชดเชย 1 การเพิ่มศูนย์เวทย์มนตร์ที่เท่ากันไม่ได้อธิบายอะไรให้ฉัน

นี่เป็นส่วนของข้อมูลที่ชดเชยหรือไม่ นี่คือสตริงปาสคาลที่คุณแปลงเป็นสตริง c ที่สิ้นสุดด้วย null โปรดบอกเราว่าเกิดอะไรขึ้น

ขอโทษด้วย แต่ฉันได้สูญเสียอาชีพการงานของฉันไปมากในการถอดรหัสปริศนาที่ไม่มีจุดหมายเช่นนี้และความอดทนของฉันที่มีต่อพวกเขาได้ลดลง เป็นตัวแปรที่มีชื่อที่ดีมากที่จะมากพอที่จะถาม?

โดยชื่อที่เหมาะสมฉันหมายถึงชื่อที่อธิบายว่าทำไมเราจึงข้ามองค์ประกอบแรก ไม่ใช่สิ่งที่พูดง่ายๆว่าเรากำลังข้ามองค์ประกอบแรก คนที่ 1 บอกว่าเป็นของตัวเอง


20
0 และ 1 ไม่ใช่ตัวเลขเวทย์มนตร์
user949300

19
@ user949300 โอ้พวกเขาอยู่ที่นี่อย่างแน่นอน พวกเขาเป็นเพียงตัวเลขที่บางครั้งก็ไม่ได้มีมนต์ขลัง เพียงเพราะ 2 เสมอหมายเลขเวทย์มนตร์ไม่ได้หมายความว่า 1 ไม่เคยเป็นหมายเลขเวทย์มนตร์ เวทมนตร์มาจากความหมายที่หายไป heck เริ่มต้นที่ 1 offset หมายความว่าอย่างไร การเพิ่ม 0 ทำได้ดีแค่ไหนที่นี่? โอ้ใช่ตัวเลขเหล่านี้น่าอัศจรรย์อย่างแน่นอน ฉันเห็นฝุ่นละอองเล็ก ๆ หยดออกมาจากพวกมัน
candied_orange

4
แน่นอนฉันจะเริ่มต้นกำหนดstatic final int LONELIEST_NUMBER = 1ในรหัส Java ของฉันทั้งหมด :-) ที่กล่าวว่าในความคิดต่อไปฉันต้องการยกเลิกการลงคะแนนคำตอบของคุณ แต่ไม่สามารถจนกว่าคุณจะแก้ไข กฎโง่ดังนั้น
user949300

6
@Eiko: หากไม่มีคำอธิบายว่าทำไมลูปเริ่มต้นที่องค์ประกอบที่สองก็รับประกันได้ว่าโปรแกรมเมอร์บำรุงรักษาบางคนจะเปลี่ยนวงเพื่อเริ่มต้นที่องค์ประกอบแรก นั่นคือเหตุผลที่ตัวเลข 1 เป็นหมายเลขเวทย์มนตร์ในบริบทนี้
Bart van Ingen Schenau

2
@BartvanIngenSchenau ฉันคิดว่าจะมีเหตุผลที่มองเห็นได้ทันทีในบริบท เช่นการเปรียบเทียบองค์ประกอบกับรุ่นก่อนของพวกเขา (ซึ่งฉันคิดว่าเป็นกรณีการใช้งานบ่อยที่สุดที่จะเริ่มต้นที่ 1 - และฉันไม่เห็นชื่อคงที่ที่มีประโยชน์ใด ๆ ที่นี่) หากองค์ประกอบแรกมีความหมายพิเศษพิเศษการออกแบบอาจเสียหายและควรมีการแก้ไขที่ดีกว่าการตั้งชื่อดัชนีนั้น ฉันไม่ได้บอกว่าไม่มีเหตุผลที่จะแนะนำตัวแปรที่นี่ มันเป็นเพียงแค่ฉันคิดว่ากรณีเหล่านี้ (หรืออาจจะควรเท่านั้น) หายากมาก
Eiko

12

คำตอบสั้น ๆ : ตัวเลือกแรกดีกว่า

ตัวเลือกที่สองเพิ่มเสียงรบกวน มันไม่น่าเป็นไปได้มากที่ 0 + 1 จะช่วยให้ผู้อ่านเข้าใจว่ามันน่าจะเป็น 0 แต่ก็คือ 1 มีโอกาสมากที่เขาจะงุนงงชั่วครู่ชั่วครู่ชั่วครู่หนึ่งและเบี่ยงเบนความสนใจจากสิ่งที่วนรอบ โดยเฉพาะอย่างยิ่งในภาษาที่อาร์เรย์ทั้งหมดเริ่มต้นที่ 0

ดังที่คนอื่นพูดถึงถ้าคุณต้องการเน้นความจริงที่ว่าลูปเริ่มต้นจาก 1 ไม่ใช่ 0 เพียงแค่เพิ่มความคิดเห็น


10

อย่าบอกเราว่าคุณกำลังข้ามรายการแรกเราจะเห็นได้ว่า อะไรคือสิ่งที่เห็นได้ชัดคือไม่ได้ว่าทำไม ดังนั้น .. ถ้ามันไม่ชัดเจนจากบริบทบอกเราทำไม:

// array[0] is just a header
for($i=1 ; $i < count(array) ; $i++){
    array[$i];
}

หรือถ้าคุณแสดงความคิดเห็นไม่ชอบสิ่งที่ชอบ:

$lastHeaderIndex = 0;
for($i = $lastHeaderIndex + 1 ; $i < count(array) ; $i++){
    array[$i];
}

อย่าใช้ความคิดเห็นและกลอุบายเพื่อเตือนเราว่าภาษาทำงานอย่างไร


6

ตัวอย่างของคุณดูเรียบร้อย ในรหัสโลกแห่งความเป็นจริงความจริงที่ว่าลูปจำเป็นต้องเริ่มต้นที่องค์ประกอบอาร์เรย์ที่สองนั้นน่าจะชัดเจนที่สุดจากบรรทัดรหัสต่อไปนี้ ตัวอย่างเช่นถ้ารหัสจริงมีลักษณะเช่นนี้

for($i=1 ; $i < count(array) ; $i++){
    array[$i-1]=array[$i];
}

จะไม่มีคำอธิบายหรือจำเป็นต้องสร้าง "0 + 1" เพื่อให้ชัดเจนว่าเหตุใดลูปเริ่มต้นที่ 1 แทนที่จะเป็น 0

อย่างไรก็ตามหากโค้ดในลูปไม่ได้อธิบายเหตุผลในแบบที่ชัดเจน (อาจarray[0]มีความหมายพิเศษและต้องจัดการแตกต่างจากองค์ประกอบที่เหลือ) จากนั้นเพิ่มความคิดเห็นที่อธิบาย แต่ก่อนที่คุณจะทำอย่างนี้ให้คิดสองครั้งถ้าคุณสามารถหลีกเลี่ยงarray[0]ความหมายพิเศษนี้และจัดระเบียบรหัสโดยรอบซึ่งอาจเป็นทางเลือกที่ดีกว่า


ในสถานการณ์เช่นรหัสตัวอย่างของคุณฉันชอบตั้งชื่อตัวแปร "oneBasedIndex" หรือ "zeroBasedIndex" แม้ว่าสิ่งที่เฉพาะเจาะจงมากขึ้นสำหรับงานนั้นจะดีกว่า
user949300

5

ไม่เคยเห็นตัวเลือก # 2 แต่ฉันชอบมัน ทำไม? ด้วยตัวเลือก # 1 ฉันสงสัยว่าโปรแกรมเมอร์ลืมว่าอาร์เรย์เริ่มต้นที่ 0 ตัวเลือก # 2 ทำให้ชัดเจนว่าพวกเขาตั้งใจเริ่มต้นที่ 1

ที่กล่าวว่าดีที่สุดในทั้งสองกรณีเพื่อเพิ่มความคิดเห็นว่าทำไมคุณถึงข้ามองค์ประกอบ

หรือถ้าคุณสามารถอธิบายได้อย่างง่ายดายว่าทำไมคุณถึงเริ่มต้นที่หนึ่งใช้ค่าคงที่ ตัวอย่างเช่นหากดูที่อาร์กิวเมนต์บรรทัดคำสั่งจะมีลักษณะดังนี้

define ('FIRST_REAL_ARGUMENT', 1);
for ($i=FIRST_REAL_ARGUMENT; ...)

โดยส่วนตัวฉันอาจใช้ความคิดเห็นแทน YMMV


ฉันจะบอกว่านอกสภาพแวดล้อมที่คุณกำลังรับมือกับผู้เริ่มต้นฉันไม่เคยมีปัญหากับเพื่อนร่วมงานที่ลืมว่าอาร์เรย์เริ่มต้นที่ศูนย์ ฉันเห็นว่ามันเกิดขึ้นถ้างานของคุณใช้ภาษาเช่น MATLAB แต่ในสภาพแวดล้อมส่วนใหญ่ฉันคิดว่าโปรแกรมเมอร์รู้ว่าพวกเขากำลังทำอะไรอยู่ และห่ามการเริ่มต้นลูปที่ 1 นั้นค่อนข้างธรรมดา มีเหตุผลสองสามข้อที่จะข้ามองค์ประกอบแรกของบางสิ่ง
Kat

@Kat เหตุผลนั้นต้องชัดเจนสำหรับผู้อ่านในอนาคต ฉันอยากจะสมมติว่าโปรแกรมเมอร์ในอนาคตไม่รู้ว่ามันกำลังทำอะไรอยู่
A1rPun

2

ฉันสงสัยว่าใครจะสับสนกับคนแรก เราทุกคนต้องทำ มากมายจนทำให้เกิดความสับสนมากขึ้น "ทำไมถึงมี 0+ พวกเขาแทนที่ผู้ประกอบการ + อย่างใด?"

คอมไพเลอร์ที่ดีจะเปลี่ยนอันที่สองให้กลายเป็นตัวแรกอยู่ดี แต่ดูเหมือนว่าคุณกำลังใช้ PHP ซึ่งถูกตีความ ดังนั้นทุกครั้งที่ล่ามกดปุ่มนั้นจะต้องเพิ่ม 0 และ 1 ไม่ใช่เรื่องใหญ่ แต่ทำไมล่ามจึงทำงานได้


2

ใช้ตัวแปรที่อธิบายจุดเริ่มต้น

คุณต้อง " ข้ามองค์ประกอบแรกในอาร์เรย์แบบ zero-based " ตัวอย่างเช่น:

skipFirstElement = 1;

for($i=$skipFirstElement ; $i < count(array) ; $i++){
    array[$i];
}

6
ฉันชอบใช้ตัวแปร แต่ฉันเกลียดชื่อนี้ ไม่ได้อธิบายว่าทำไมคุณจึงข้ามองค์ประกอบแรก 1 บอกฉันว่าต่อไป ตัวแปรที่ดีที่ต้องเปลี่ยนเมื่อมีการเปลี่ยนแปลงค่าคืออะไร ฉันรู้ว่า OP ไม่ได้ให้เหตุผลว่าทำไมเราถึงเลือกชื่อที่ดีที่คุณจะต้องทำด้วยเหตุผล หากไม่มีชื่อที่ดีกว่าฉันอยากได้ 1 คนกลับมา
candied_orange

@CandiedOrange ฉันเห็นด้วยกับคุณว่าชื่อตัวแปรควรมีความหมายมากกว่า แต่ปัญหาที่เกิดขึ้นไม่ได้อธิบายว่าทำไมเขาถึงต้องการข้ามค่าแรก ประเด็นของฉันคือฉันแค่ยกตัวอย่างผู้เขียนสามารถเลือกชื่อที่ดีที่สุดสำหรับเขา
catta

กรุณาอย่าสอนด้วยวิธีนี้ มันทำให้เกิดความสับสนมากพอ สำหรับนักเขียนโค้ดจำนวนมากนั้นจะเข้าถึงชื่อที่ง่ายที่สุดเพื่อให้สามารถกลับไปเขียนโค้ดที่เข้าใจยากได้ อย่างจริงจังฉันค่อนข้างจะจัดการกับ 1 กว่านี้
candied_orange

1
//We are skipping the first element because...    
if ($i==0)  
{    continue;      } 

หากมีใครครอบงำด้วยลูปทั้งหมดเริ่มต้นที่ศูนย์คุณสามารถใช้คำสั่งดำเนินการต่อ เพิ่มความคิดเห็นว่าเพราะเหตุใดคุณจึงไม่ข้าม


2
ปัญหาของตัวเลือกนี้หมายความว่าเรากำลังจะประเมินสิ่งนี้สำหรับทุกองค์ประกอบเดียวโดยเพิ่ม n การเปรียบเทียบเพิ่มเติมกับลูปในขณะที่เพียงแค่ข้ามสิ่งแรกผ่านวิธีอื่น (เปลี่ยนอาร์เรย์โดยเริ่มจาก i = 1 ไม่ว่าอะไรก็ตาม ) หมายถึงการทำงานที่คุณต้องการเท่านั้น
ค่าธรรมเนียมของเควิน

3
@KevinFee หากคุณไม่ได้จัดการกับอาร์เรย์ขนาดใหญ่ฉันจะบอกว่าการเปรียบเทียบที่ง่ายกว่านี้จะไม่เป็นปัญหา และฉันก็ค่อนข้างชอบif first then skipคำอธิบายที่มีความคิดเห็นว่าทำไม แม้จะไม่มีบริบทการแก้ปัญหาก็ไม่มี "ดีที่สุด"
Ivan Pintar

-2

สิ่งที่ฉันจะทำคือลบองค์ประกอบแรกก่อนที่จะวนลูป สร้างอาร์เรย์ใหม่หากคุณต้องการ อธิบายในความคิดเห็นว่าทำไมคุณถึงทำ และจากนั้นทำแบบง่าย ๆ foreach

$arrayCopy = $array; // in case you don't want to touch the original array
array_shift($arrayCopy); // removing first element because of X reason.
foreach($arrayCopy => $element) { 
    // do stuff
}

วิธีนี้เจตนาของคุณชัดเจนอย่างสมบูรณ์แบบ

หากต้องการชี้แจงเพิ่มเติมคุณสามารถรวมโค้ดในวิธีการด้วยชื่อที่เหมาะสมเพื่อทำให้สิ่งต่าง ๆ ชัดเจนขึ้น

function doStuffToAllButTheFirst($array) { // this copies the original array, so there are no sideffects
    array_shift($array);
    foreach($array => $element) { // do stuff }  
}

อย่างไรก็ตามสิ่งเหล่านี้ยังคงไม่มีบริบท คุณต้องการทำอะไรกับองค์ประกอบ คุณจะส่งคืนอาร์เรย์ใหม่หรือไม่ คุณสนใจเกี่ยวกับต้นฉบับและอาร์เรย์ใหม่หลังจากคุณdoStuff()หรือไม่

อย่างไรก็ตามไม่มีคำตอบที่ชัดเจนที่นี่และการตัดสินใจว่าจะทำให้โค้ดอ่านอย่างไรนั้นขึ้นอยู่กับบริบทอย่างมาก


1
ฉันชอบสิ่งนี้เพราะฉันไม่จำเป็นต้องจัดการกับดัชนีตอนนี้ซึ่งเป็นข้อดีอยู่เสมอ
Tomas Zubiri

1
ข้อเสียของที่นี่คือถ้าคุณไม่ต้องการผลข้างเคียงคุณต้องคัดลอกอาร์เรย์ทั้งหมด
Tomas Zubiri

1
และถ้าเหตุผลที่เราเริ่มต้นที่ 1 เป็นเพราะเรากำลังทำ$array[$i-1] = $array[$i]หรือสิ่งที่คล้ายกันตามคำตอบของ @ DocBrown?
ค่าธรรมเนียมของเควิน

1
มันดูน่ากลัวสำหรับฉัน นอกเหนือจากความไร้ประสิทธิภาพผลข้างเคียงและการไร้ความสามารถในการแก้ไขกรณีการใช้งานทั่วไปสำหรับ1(ดูความคิดเห็นของ Kevin Lee) มันไม่ได้ทำให้โค้ดชัดเจนขึ้นเลย ผู้อ่านจะต้องเข้าใจ array_shift สิ่งที่มันทำงานวิธีการ รหัสบรรทัดนี้อาจเป็นจุดบกพร่องหรือไม่ มันดัดแปลงอาร์เรย์หรือคืนค่าใหม่หรือไม่? มันแทรกองค์ประกอบหรือลบออกหรือไม่ มันเปลี่ยนดัชนีหรือไม่? ฉันล้มเหลวในการดูว่าการใช้การวนซ้ำแบบใดแบบหนึ่งจะไม่เป็นการปรับปรุงอย่างมากในฟังก์ชันนั้น (และตั้งชื่อให้เข้าใจได้ง่ายในทันที)
Eiko

1
คำตอบของคำถามเหล่านี้ขึ้นอยู่กับบริบทเป็นอย่างมาก และสำหรับประสิทธิภาพฉันจะบอกล่วงหน้าทุกวัน ... ความแตกต่างด้านประสิทธิภาพใด ๆ ก็เกือบจะมองไม่เห็นในกรณีส่วนใหญ่
Ivan Pintar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.