Döngü tabanlı bir dizindeki ilk öğeyi atlamanın net yolu


9

Ben sıfır tabanlı bir dizi ilk öğeyi atlamak gerekir bir for döngüsü var.

Bunlardan hangisi niyetlerimi daha net gösteriyor?

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

veya

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

28
Her ikisi $i=2-1de, üstün yoldur. : /
yannis

7
Muhtemelen ilk seçeneği seçer ve ilk öğenin neden atlanması gerektiğini açıklamak için bir yorum eklerim.
Vincent Savard

3
Açıklık amaçladığım şey, soruyu düzenledim. Bu daha açık mı?
Tomas Zubiri

10
PHP kullanmamak en iyi yoldur.
kedi

3
PHP'nin foreach yapısı var mı? Yapabilirsin foreach ($i in range(1, count))(PHP'de nasıl görünüyorsa). Ya da foreach ($item in array.skip(1))bir C # kişinin yapacağı gibi bir şey.
usr

Yanıtlar:


23

İkisinden de nefret ediyorum.

Sihirli sayılar kullanabileceğinizi kim söyledi? Eğer 1 ofsetinden başlayacaksanız, neden 1 ofsetinden başladığınızı bize anlatmaya ne dersiniz? Eşit derecede sihirli bir sıfır eklemek bana hiçbir şeyi açıklamaz.

Bu yük yükü dengesi mi? Bu bir boş sonlandırılmış c dizesine dönüştürdüğünüz bazı pascal dizesi mi? Lütfen bize neler olduğunu anlat.

Üzgünüm, ama kariyerimin büyük bir kısmını bunun gibi anlamsız gizemleri çözdüm ve onlara olan sabrım zayıfladı. Mı iyi adla bir değişken sormak için çok gerçekten?

İyi adla, ilk öğeyi neden atladığımızı açıklayan bir ad kastediyorum. Sadece ilk elementi atladığımızı söyleyen bir şey değil. 1 bana kendi başına olduğunu söyledi.


20
0 ve 1 sihirli sayılar değildir.
user949300

19
@ user949300 Oh kesinlikle buradalar. Bunlar sadece zaman zaman büyülü olmayan rakamlardır. 2'nin her zaman sihirli bir sayı olması, 1'in asla sihirli bir sayı olmadığı anlamına gelmez. Sihir eksik anlamdan gelir. 1 ofsetten başlamak burada ne anlama geliyor? Burada 0 eklemek ne işe yarar? Ah evet bu sayılar kesinlikle büyülü. Pixie tozunun damladığını görebiliyorum.
candied_orange

4
Tabii, static final int LONELIEST_NUMBER = 1tüm Java kodumu tanımlamaya başlayacağım . :-) Bu, daha fazla düşündüğümde cevabınızı küçümsemek istediğimi, ancak siz düzenlemediğiniz sürece yapamayacağınızı söyledi. Aptal SO kuralı?
user949300

6
@Eiko: Döngünün neden ikinci elemandan başladığına dair bir açıklama yoksa, bazı bakım programcılarının ilk elemandan başlayacak şekilde döngüyü değiştireceği neredeyse garanti edilir. Bu yüzden 1 rakamı bu bağlamda sihirli bir sayıdır.
Bart van Ingen Schenau

2
@BartvanIngenSchenau Bu bağlamda hemen görünür bir neden olacağını varsaydım. Öğeleri öncekilerle karşılaştırmak gibi (1'den başlamak için en sık kullanılan durum olduğunu düşündüm - ve burada herhangi bir yararlı sabit isim göremiyorum). İlk öğenin çok özel bir anlamı varsa, tasarım bozulabilir ve bu dizini adlandırmaktan daha iyi düzeltmeler olmalıdır. Buraya bir değişken tanıtmak için asla bir neden olmadığını söylemiyorum. Sadece bu davaların çok nadir olduğunu düşünüyorum (ya da belki de olmalı).
Eiko

12

Kısa cevap: ilk seçenek daha iyidir.

İkinci seçenek sadece gürültü ekler. 0 + 1'in okuyucunun 0 olabileceğini anlamasına yardımcı olması çok düşük bir ihtimaldir, ancak 1'dir. Özellikle tüm dizilerin 0'dan başladığı bir dilde.

Daha önce de belirtildiği gibi, döngünün 0'dan değil 1'den başladığını vurgulamak istiyorsanız, sadece bir yorum ekleyin.


10

Bize ilk öğeyi atladığınızı söyleme - bunu görebiliriz. Açık olmayan şey neden . Yani .. bağlamdan belli değilse, bize nedenini söyleyin:

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

Veya yorumdan kaçınıyorsanız, şöyle bir şey:

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

Bize dilin nasıl çalıştığını hatırlatmak için yorum ve hile yapmayın .


6

Örneğiniz yapmacık görünüyor. Gerçek dünya kodunda, döngülerin ikinci dizi öğesinde başlaması gerektiği gerçeği büyük olasılıkla aşağıdaki kod satırlarında açıktır. Örneğin, gerçek kod şöyle görünürse

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

döngünün neden 0 yerine 1'de başladığını açıklığa kavuşturmak için hiçbir açıklama veya "0 + 1" yapısı gerekmez.

Ancak, döngü içindeki kod nedenleri bu kadar açık bir şekilde açıklamazsa (belki array[0]de özel bir anlamı vardır ve geri kalan öğelerden farklı bir şekilde ele alınması gerekir), açıklayıcı bir yorum ekleyin. Ancak bunu yapmadan önce, array[0]bu özel anlama sahip olmaktan kaçınabiliyorsanız iki kez düşünün ve muhtemelen daha iyi bir alternatif olan çevre kodunu yeniden düzenleyin.


Örnek kod gibi durumlarda "oneBasedIndex" veya "zeroBasedIndex" değişkenlerini adlandırmak istiyorum. Bu görev için daha spesifik bir şey daha iyi olsa da.
user949300

5

Hiç seçenek # 2 görmedim, ama hoşuma gitti. Neden? Seçenek # 1 ile programlayıcının dizilerin 0'dan başlamasını unuttuğunu merak ediyorum. Seçenek # 2, kasıtlı olarak 1'den başladıklarını daha net hale getirir.

Bununla birlikte, her iki durumda da neden öğeyi atladığınıza yorum eklemek için en iyisi.

Veya neden birinden başladığınızı kolayca açıklayabiliyorsanız, bir sabit kullanın. Örneğin, komut satırı bağımsız değişkenlerine bakıyorsanız,

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

Şahsen, YMMV yerine muhtemelen bir yorum kullanırdım.


Yeni başlayanlarla uğraştığınız ortamların dışında, iş arkadaşlarının dizilerin sıfırdan başladığını unutma sorununu hiç yaşamadığımı söyleyeceğim. Çalışmanız MATLAB gibi bir dil kullansaydı bunun olduğunu görebiliyordum, ancak çoğu ortamda programcının ne yaptığını bildiğini varsayabilirim. Ve heck, 1'de bir döngü başlatmak oldukça yaygındır. Bir şeyin ilk unsurunu atlamak için birkaç neden var.
Kat

@Kat Bu nedenin gelecekteki okuyucular için açık olması gerekir. Gelecekteki bir programcının ne yaptığını bilmediğini varsaymayı tercih ederim.
A1rPun

2

Birinin ilkinin kafasını karıştıracağından şüpheliyim. Hepimiz bunu yapmak zorundaydık. Öyle ki, ikincisinin kafasını karıştırması çok daha olası. "Neden orada 0+ var? + Operatörünü bir şekilde geçersiz kıldılar mı?"

İyi bir derleyici, ikincisini yine de ilkine çevirecektir, ancak yorumlanmış PHP kullanıyorsunuz gibi görünüyor. Tercüman bu döngüye her girdiğinde, aslında 0 ve 1 eklemesi gerekecek. Çok önemli değil, ama tercümanı neden işe yaratıyor?


2

Başlangıç ​​noktasını açıklayan bir değişken kullanın.

" Sıfır tabanlı bir dizideki ilk öğeyi atlamanız " gerekir , örneğin:

skipFirstElement = 1;

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

6
Bir değişken kullanmayı seviyorum ama bu addan nefret ediyorum. NEDEN ilk elemanı atladığınızı açıklamıyor. A 1 bana yine de söylüyor. Değer değiştiğinde yeniden adlandırılması gereken bir değişkenin faydası nedir? OP'nin bize neden bir ipucu vermediğini biliyorum, bu yüzden iyi bir isim seçmek için bir neden oluşturmalısınız. Daha iyi bir isim olmadan ben 1 geri tercih ediyorum.
candied_orange

@CandiedOrange Değişken adının daha anlamlı olması gerektiğine katılıyorum, ancak sunulduğu gibi sorun neden ilk değeri atlamak istediğini açıklamıyor. Demek istediğim, sadece bir örnek vereyim, yazar onun için en iyi ismi seçebilir.
catta

Lütfen bu şekilde öğretmeyin. Bu yeterince kafa karıştırıcı. Birçok kodlayıcıya, kodun anlaşılması zor bir şekilde yazmaya geri dönebilecekleri en kolay isme ulaşacaklardır. Cidden, ben 1'den daha çok uğraşmayı tercih ederim.
candied_orange

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

Eğer biri sıfırdan başlayan tüm döngülere takıntılıysa, bir devam ifadesi kullanabilirsiniz. Neden normalde atlamayacağınıza göre atladığınıza bir yorum ekleyin.


2
Bu seçenekle ilgili sorun, bunu her bir öğe için değerlendireceğimiz, döngüye n ek karşılaştırma ekleyeceğimiz ve ilkini başka bir yöntemle atlayacağımız anlamına gelir (diziyi değiştirmek, i = 1 ile başlayarak, her neyse) ) yalnızca ihtiyacınız olan işi yapmak anlamına gelir.
Kevin Fee

3
@KevinFee Büyük dizilerle uğraşmıyorsanız, bu simle karşılaştırmasının bir sorun olmayacağını söyleyebilirim. Ve if first then skipnedenini açıklayan bir yorum ile açıklığı çok seviyorum . Yine de bağlam olmadan çözümlerin hiçbiri "en iyi" değildir
Ivan Pintar

-2

Yaptığım şey, döngüden önce ilk öğeyi kaldırmak. Gerekirse yeni bir dizi oluşturun. Bir yorumda neden bunu yaptığınızı açıklayın. Ve sonra basit bir foreach yapın.

$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
}

Bu şekilde niyetiniz çok açık.

Daha fazla açıklığa kavuşturmak için, kodu işleri daha net hale getirmek için uygun bir adla bir yönteme sarabilirsiniz.

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

Ancak bunların hepsinin bağlamı hala eksik. Elementlerle ne yapmak istersiniz? Yeni diziyi iade edecek misiniz? Sizden sonraki orijinal ve yeni diziyi önemsiyor musunuz doStuff()?

Her neyse, burada net bir cevap yok ve kodun nasıl okunabilir olacağına karar vermek büyük ölçüde bağlama bağlı.


1
Bunu beğendim çünkü şimdi endekslerle uğraşmam gerekmiyor, ki bu her zaman bir artı.
Tomas Zubiri

1
Buradaki dezavantaj, yan etkiler istemiyorsanız, tüm diziyi kopyalamanız gerektiğidir.
Tomas Zubiri

1
Peki $array[$i-1] = $array[$i]ya 1'de başlamamızın sebebi @ DocBrown'un cevabına göre yapıyoruz ya da benzer bir şeyse?
Kevin Fee

1
Bu bana korkunç geliyor. Tüm verimsizlik, yan etkiler ve oldukça yaygın kullanım durumlarını çözememenin yanı sıra 1(Kevin Lee'nin yorumuna bakın), kodu hiç netleştirmiyor. Okuyucu array_shift'i, ne işe yaradığını, nasıl çalıştığını anlamalıdır. Belki bu kod satırı bir hatadır? Diziyi değiştirir mi yoksa yenisini döndürür mü? Bir eleman ekliyor mu yoksa bir eleman mı çıkarıyor? Endeksleri değiştiriyor mu değiştirmiyor mu? Tek tabanlı bir döngü kullanmanın bu işlevde nasıl büyük bir gelişme olmayacağını göremiyorum (ve adı verildi, anında anlaşılabilir).
Eiko

1
Bu soruların cevapları büyük ölçüde bağlama bağlıdır. Ve verimliliğe gelince, her gün bir öngörü devralırım ... Herhangi bir performans farkı çoğu durumda görünmez.
Ivan Pintar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.