Maneira clara de ignorar o primeiro elemento em um índice baseado em loop

9

Eu tenho um loop for, onde devo pular o primeiro elemento em uma matriz baseada em zero.

Qual destes mostra minhas intenções mais claramente?

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

ou

for($i=0+1 ; $i < count(array) ; $i++){
    array[$i];
}
Tomas Zubiri
fonte
28
Nem, $i=2-1é o caminho superior. : /
yannis
7
Eu provavelmente iria para a primeira opção e adicionaria um comentário para explicar por que o primeiro elemento precisa ser ignorado.
Vincent Savard 07/10
3
Clareza é o que estou buscando, editei a pergunta. Isso é mais claro?
Tomas Zubiri
10
Não usar PHP é a maneira superior.
gato
3
O PHP tem uma construção foreach? Você poderia fazer foreach ($i in range(1, count))(seja lá o que for que parece em PHP). Ou algo parecido foreach ($item in array.skip(1))com o que uma pessoa C # faria.
usr

Respostas:

23

Eu odeio os dois.

Quem disse que você poderia usar números mágicos? Se você vai começar com um deslocamento de 1, que tal nos dizer POR QUE você está começando com um deslocamento de 1. Adicionar um zero igualmente mágico não explica nada para mim.

Esse é o deslocamento da carga útil? É alguma string pascal que você está convertendo em uma string c terminada nula? Por favor, diga-nos o que está acontecendo.

Desculpe, mas perdi muito da minha carreira decodificando mistérios inúteis como esse e minha paciência com eles se esgotou. É uma variável com um nome decente realmente muito para pedir?

Por nome decente, quero dizer um nome que explica POR QUE estamos pulando o primeiro elemento. Não é algo que simplesmente diz que estamos pulando o primeiro elemento. O 1 me disse isso por conta própria.

candied_orange
fonte
19
0 e 1 não são números mágicos.
user949300
19
@ user949300 Oh, certamente eles estão aqui. São simplesmente números que ocasionalmente não são mágicos. Só porque 2 é sempre um número mágico, não significa que 1 nunca seja um número mágico. A mágica vem da falta de significado. O que diabos começar com um deslocamento de 1 significa aqui? Qual a vantagem de adicionar um 0 aqui? Ah, sim, esses números são certamente mágicos aqui. Eu posso ver a poeira dos duendes pingando deles.
Candied_orange # 7/16
4
Claro, vou começar a definir static final int LONELIEST_NUMBER = 1em todo o meu código Java. :-) Dito isso, pensando melhor, gostaria de cancelar sua resposta, mas não posso, a menos que você a edite. Regra tão boba?
user949300
6
@Eiko: Se não houver explicação para o início do loop no segundo elemento, é praticamente garantido que algum programador de manutenção altere o loop para iniciar no primeiro elemento. É por isso que o número 1 é um número mágico neste contexto.
Bart van Ingen Schenau
2
@BartvanIngenSchenau Presumi que haveria uma razão imediatamente visível dentro do contexto. Como comparar elementos com seus antecessores (que eu pensei ser o caso de uso mais frequente para começar em 1 - e não consigo ver nenhum nome constante útil aqui). Se o primeiro elemento tiver algum significado ultra-especial, o design poderá estar quebrado e deve haver correções melhores do que nomear esse índice. Eu não digo que nunca há uma razão para introduzir uma variável aqui. Só acho que esses casos são (ou talvez só devam ser) muito raros.
Eiko
12

Resposta curta: a primeira opção é melhor.

A segunda opção apenas adiciona ruído. É muito improvável que 0 + 1 ajude o leitor a entender que poderia ter sido 0, mas é 1. Muito mais provavelmente ele ficará intrigado por um breve momento e distraído do significado do loop. Especialmente em um idioma em que todas as matrizes começam em 0.

Como mencionado anteriormente, se você quiser enfatizar o fato de que o loop começa em 1, não em 0, basta adicionar um comentário.

Florian F
fonte
10

Não nos diga que você está pulando o primeiro item - podemos ver isso. O que não é óbvio é o porquê . Então .. se não for óbvio no contexto, diga-nos por que:

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

Ou, se você não gosta de comentar, algo como:

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

Não use comentários e truques para nos lembrar como o idioma funciona.

svidgen
fonte
6

Seu exemplo parece artificial. No código do mundo real, o fato de os loops precisarem iniciar no segundo elemento da matriz é provavelmente mais óbvio nas seguintes linhas de código. Por exemplo, se o código real se parecer com isso

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

não haveria explicação ou construção "0 + 1" necessária para esclarecer por que o loop inicia em 1 em vez de 0.

No entanto, se o código dentro do loop não explicar os motivos de maneira tão óbvia (talvez array[0]tenha um significado especial e deva ser tratado de maneira diferente dos elementos restantes), adicione um comentário explicativo. Porém, antes de fazer isso, pense duas vezes se puder evitar array[0]esse significado especial e reorganize o código ao redor, o que provavelmente seria a melhor alternativa.

Doc Brown
fonte
Em situações como o seu código de exemplo, gosto de nomear as variáveis ​​"oneBasedIndex" ou "zeroBasedIndex". Embora algo ainda mais específico para essa tarefa fosse melhor.
user949300
5

Nunca vi a opção 2, mas eu gosto. Por quê? Com a opção 1, gostaria de saber se o programador esqueceu que as matrizes começam em 0. A opção 2 deixa mais claro que eles estão deliberadamente começando em 1.

Dito isto, melhor nos dois casos, adicionar um comentário por que você está pulando o elemento.

Ou, se você pode descrever facilmente por que está começando uma, use uma constante. Por exemplo, se analisar os argumentos da linha de comando, algo como

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

Pessoalmente, eu provavelmente usaria apenas um comentário, YMMV.

user949300
fonte
Eu direi que fora dos ambientes em que você está lidando com iniciantes, nunca tive o problema de colegas de trabalho esquecerem que as matrizes começam do zero. Eu poderia ver isso acontecendo se o seu trabalho também usasse uma linguagem como MATLAB, mas na maioria dos ambientes, eu assumiria que o programador sabia o que estava fazendo. E, diabos, iniciar um loop em 1 é bastante comum. Existem algumas razões para pular o primeiro elemento de algo.
Kat
@Kat Essa razão precisa ser clara para os futuros leitores. Prefiro assumir que um futuro programador não sabe o que está fazendo.
precisa
2

Duvido que alguém se confunda com o primeiro. Todos nós tivemos que fazer isso. Tanto é assim que o segundo é muito mais provável que confunda. "Por que existe um 0+? Eles substituíram o operador + de alguma forma?"

Um compilador decente transformará o segundo no primeiro de qualquer maneira, mas parece que você está usando PHP, que é interpretado. Então, toda vez que o intérprete atingir esse loop, ele precisará adicionar 0 e 1. Não é grande coisa, mas por que fazer o intérprete fazer o trabalho?

Kevin Fee
fonte
2

Use uma variável que explique o ponto inicial.

Você precisa " pular o primeiro elemento em uma matriz baseada em zero ", portanto, por exemplo:

skipFirstElement = 1;

for($i=$skipFirstElement ; $i < count(array) ; $i++){
    array[$i];
}
catta
fonte
6
Eu gosto de usar uma variável, mas odeio esse nome. Isso não explica por que você está pulando o primeiro elemento. A 1 me diz isso de qualquer maneira. Qual a utilidade de uma variável que precisa ser renomeada quando seu valor é alterado? Sei que o OP não nos deu nenhuma pista do motivo pelo qual, para escolher um bom nome, você terá que inventar um motivo. Sem um nome melhor, eu prefiro ter o 1 de volta.
Candied_orange 11/10
@CandiedOrange Concordo com você que o nome da variável deve ser mais significativo, mas o problema apresentado não explica por que ele quer pular o primeiro valor. O que quero dizer é que, basta dar um exemplo, o autor pode escolher um nome que seja melhor para ele.
catta 12/10
Por favor, não ensine dessa maneira. Isso já é bastante confuso. Para muitos codificadores, eles buscarão o nome mais fácil possível, para que possam voltar a escrever códigos difíceis de entender. Sério, eu prefiro lidar com o 1 do que com isso.
Candied_orange 12/10
1
//We are skipping the first element because...    
if ($i==0)  
{    continue;      } 

Se alguém é obsessivo com todos os loops começando em zero, você pode usar uma instrução continue. Adicione um comentário ao motivo pelo qual você está pulando, pois normalmente não o faria.

Jon Raynor
fonte
2
O problema com esta opção significa que avaliaremos isso para cada elemento, adicionando n comparações adicionais ao loop, enquanto simplesmente pular o primeiro por outro método (alternando a matriz, começando com i = 1, qualquer que seja ) significa apenas fazer o trabalho que você precisa.
Kevin Fee
3
@ KevinFee Se você não está lidando com matrizes massivas, eu diria que essa comparação simples não será um problema. E eu gosto bastante da explicação if first then skipcom um comentário dizendo o porquê. Ainda sem contexto, nenhuma das soluções é "melhor"
Ivan Pintar
-2

O que eu faria é remover o primeiro elemento antes de fazer o loop. Crie uma nova matriz, se necessário. Explique em um comentário por que você está fazendo isso. E então apenas faça um foreach simples.

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

Dessa forma, sua intenção é perfeitamente clara.

Para esclarecer melhor, você pode agrupar o código em um método com um nome apropriado para tornar as coisas mais claras.

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

No entanto, tudo isso ainda está faltando no contexto. O que você quer fazer com os elementos? Você retornará a nova matriz? Você se importa com o original e o novo array depois de você doStuff()?

De qualquer forma, não há uma resposta clara aqui, e decidir como tornar o código legível depende muito do contexto.

Ivan Pintar
fonte
11
Gosto disso porque não preciso lidar com índices agora, o que é sempre uma vantagem.
Tomas Zubiri 07/10
11
A desvantagem aqui é que, se você não quiser efeitos colaterais, precisará copiar toda a matriz.
Tomas Zubiri 07/10
11
E se o motivo de começarmos com 1 for porque estamos fazendo $array[$i-1] = $array[$i]ou algo semelhante, conforme a resposta do @ DocBrown?
Kevin Fee
11
Isso me parece horrível. Além de toda a ineficiência, efeitos colaterais e incapacidade de resolver casos de uso bastante comuns 1(veja o comentário de Kevin Lee), ele não torna o código mais claro. O leitor deve entender array_shift, o que faz, como funciona. Talvez essa linha de código seja um bug? Modifica a matriz ou retorna uma nova? Ele insere um elemento ou remove um? Isso muda os índices ou não? Não vejo como o uso de um loop de base única não seria uma grande melhoria nessa função (e, devido ao nome, instantaneamente compreensível).
Eiko
11
As respostas para essas perguntas são altamente dependentes do contexto. E quanto à eficiência, eu recomendaria a qualquer dia ... Qualquer diferença de desempenho é quase invisível na maioria dos casos.
Ivan Pintar 08/10