Pergunta

Ao rever, eu às vezes encontrar esse tipo de loop:

i = begin
while ( i != end ) {    
   // ... do stuff
   if ( i == end-1 (the one-but-last element) ) {
      ... do other stuff
   }
   increment i
}

Então eu faço a pergunta: você escrever este

?
i = begin
mid = ( end - begin ) / 2 // (the middle element)
while ( i != end ) {    
   // ... do stuff
   if ( i > mid ) {
      ... do other stuff
   }
   increment i
}

Na minha opinião, este bate a intenção de escrever um loop: você laço porque há algo comum a ser feito para cada um dos elementos. Utilizando esta construção, para alguns dos elementos que você fazer algo diferente. Assim, concluo, é necessário um circuito separado para esses elementos:

i = begin
mid = ( end - begin ) / 2 //(the middle element)
while ( i != mid ) {    
   // ... do stuff
   increment i
}

while ( i != end ) {
   // ... do stuff
   // ... do other stuff
   increment i
}

Agora, eu mesmo vi um questão no SO sobre como escrever o if cláusula em uma boa maneira ... E eu tenho triste:. algo não está certo aqui

Estou errado? Se assim for, o que é tão bom sobre desordenar o corpo do laço com casos especiais, que você está ciente de antecipadamente, no momento da codificação?

Foi útil?

Solução

@xtofl,

Concordo com a sua preocupação.

milhão de vezes eu encontrei problema semelhante.

De qualquer desenvolvedor adiciona um tratamento especial para o primeiro ou para o último elemento.

Na maioria dos casos, vale a pena para apenas loop do startIdx 1 endIdx + ou - 1 elemento ou até mesmo dividir um longo ciclo em várias voltas mais curtas.

Em casos muito raros, não é possível fazer um loop de divisão.

Na minha opinião incomum coisas devem ser tratadas fora do circuito sempre que possível.

Outras dicas

Eu não acho que esta questão deve ser respondida por um princípio (por exemplo, "em um loop, tratar cada elemento igualmente"). Em vez disso, você pode olhar para dois fatores para avaliar se uma aplicação é bom ou ruim:

  1. Runtime efetividade -? Que o código compilado correr rápido, ou seria fazê-lo mais rápido de forma diferente
  2. manutenção Código - É fácil (para outro desenvolvedor) para entender o que está acontecendo aqui?

Se ele é mais rápido e o código é mais legível, fazendo tudo em um loop, fazê-lo dessa maneira. Se é mais lento e menos legível, fazê-lo de outra maneira.

Se ele é mais rápido e menos legível, ou mais lento, mas mais legível, descobrir qual dos fatores que mais importa no seu caso específico, e então decidir como fazer um loop (ou não loop).

Eu sei que eu já vi isso quando as pessoas tentaram se juntar elementos de uma matriz em uma string separada por vírgula:

for(i=0;i<elements.size;i++) {
   if (i>0) {
     string += ','
   }
   string += elements[i]
}

Você quer ter que se cláusula de lá, ou você tem que duplicar a string + = linha novamente no final.

A solução óbvia nesse caso é

string = elements.join(',')

Mas o método de junção faz o mesmo circuito internamente. E nem sempre há um método para fazer o que quiser.

Eu vim para uma realização que quando eu coloco casos especiais em um loop, normalmente estou a ser demasiado inteligente para o meu próprio bem.

No último trecho que você postou, você está repetindo código para // .... fazer coisas.

Faz sentido de manter 2 loops quando você tem conjunto completamente diferente de operações em um conjunto diferente de índices.

i = begin
mid = ( end - begin ) / 2 //(the middle element)
while ( i != mid ) {    
   // ... do stuff
   increment i
}

while ( i != end ) {
   // ... do other stuff
   increment i
}

Este não é o caso, você ainda quiser manter um único loop. No entanto restos fato de você ainda salvar (fim - começam) / 2 Número de comparações. Então, tudo se resume a saber se você quer que seu código para olhar puro ou você deseja salvar alguns ciclos de CPU. Chamada é sua.

Eu acho que você tem que inteiramente pregado. A maioria das pessoas caem na armadilha de incluir desvios condicionais em loops, quando poderiam fazê-los fora:., Que é simplesmente mais rápido

Por exemplo:

if(items == null)
    return null;

StringBuilder result = new StringBuilder();
if(items.Length != 0)
{
    result.Append(items[0]); // Special case outside loop.
    for(int i = 1; i < items.Length; i++) // Note: we start at element one.
    {
        result.Append(";");
        result.Append(items[i]);
    }
}
return result.ToString();

E o caso do meio que você descreveu é simplesmente desagradável . Imagine se esse código cresce e precisa ser reformulado em diferentes métodos.

A menos que você estiver analisando XML laços devem ser mantidos tão simples e concisa possível.

Eu acho que você está certo sobre o loop sendo feitos para lidar com todos os elementos igualmente. Infelizmente, por vezes, há casos especiais embora e estes devem ser tratados dentro da construção de loop via se declarações.

Se existem muitos casos especiais que você provavelmente deve pensar em chegar com alguma forma de lidar com os dois conjuntos diferentes de elementos em construções separadas.

Eu prefiro simplesmente, excluir o elemento do circuito e dar um tratamento separado fora do loop

Por exemplo: Vamos considerar o caso de EOF

i = begin
while ( i != end -1 ) {    
   // ... do stuff for element from begn to second last element
   increment i
}

if(given_array(end -1) != ''){
   // do stuff for the EOF element in the array
}

Claro, especial-invólucro coisas em um loop que pode ser puxado para fora é bobagem. Eu não iria duplicar o do_stuff quer embora; Eu quer colocá-lo em uma função ou uma macro para que eu não copiar e colar código.

Outra coisa que eu odeio ver é o para caso padrão :

for (i=0; i<5; i++)
{
  switch(i)
  {
    case 0:
      // something
      break;
    case 1:
      // something else
      break;
    // etc...
  }
}

Eu vi isso no código real.

Qual deles executa melhor?

Se o número de itens é muito grande, então eu sempre loop de uma vez, especialmente se você está indo para executar alguns operação em cada item. O custo de avaliar a condicional é provável que seja menos de loop duas vezes.

Opa, é claro que você não looping duas vezes ... No caso de dois circuitos, é preferível. No entanto, eu afirmo que a principal consideração deve ser o desempenho. Não há nenhuma necessidade de se incorrer na condicional no circuito (N vezes) se você pode dividir o trabalho por uma simples manipulação dos limites de alça (uma vez).

O caso especial deve ser feito fora do loop se é apenas para ser executada uma vez.

No entanto, pode haver um índice ou alguma outra variável (s) que são apenas mais fácil de manter dentro do loop devido ao escopo. Também pode haver uma razão contextual para manter todas as operações na estrutura de dados em conjunto dentro da estrutura de controle loop, embora eu acho que é um argumento fraco por conta própria.

Seu apenas em usá-lo como por necessidade e conveniência. Há, como tal, não menciona a elementos tratar da mesma forma e não há certamente nenhum dano boates as características que a linguagem oferece.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top