Não há nada inerentemente errado ou necessariamente ruim nos loops aninhados. No entanto, eles têm certas considerações e armadilhas.
Os artigos aos quais você foi direcionado, provavelmente em nome da brevidade ou devido a um processo psicológico conhecido como sendo queimado, pulando os detalhes.
Ser queimado é quando você tem uma experiência negativa de algo com o ser implicante e evita-o. Por exemplo, eu poderia cortar legumes com uma faca afiada e me cortar. Eu poderia então dizer que facas afiadas são ruins, não as use para cortar legumes para tentar tornar impossível que essa experiência ruim aconteça novamente. Isso é obviamente muito impraticável. Na realidade, você só precisa ter cuidado. Se você está dizendo para outra pessoa cortar legumes, você tem uma sensação ainda mais forte disso. Se eu estivesse instruindo as crianças a cortarem legumes, sentiria muito forte que lhes dissessem para não usarem uma faca afiada, especialmente se não puder supervisioná-las de perto.
O problema da programação é que você não alcançará o pico de eficiência se sempre preferir segurança primeiro. Nesse caso, as crianças só podem cortar legumes macios. Confrontado com qualquer outra coisa e eles só vão fazer uma bagunça usando uma faca sem corte. É importante aprender o uso adequado de loops, incluindo loops aninhados, e você não pode fazer isso se eles forem considerados ruins e você nunca tentar usá-los.
Como muitas respostas aqui apontam que um loop aninhado é uma indicação das características de desempenho do seu programa que podem ficar exponencialmente piores a cada aninhamento. Ou seja, O (n), O (n ^ 2), O (n ^ 3) e assim por diante, que compreende O (n ^ profundidade), em que profundidade representa quantos ciclos você aninhou. À medida que o seu aninhamento cresce, o tempo necessário aumenta exponencialmente. O problema é que não é uma certeza que sua complexidade de tempo ou espaço seja essa (muitas vezes a * b * c, mas nem todos os loops de ninho podem ser executados o tempo todo) nem é uma certeza que você tem um problema de desempenho mesmo que seja isso.
Para muitas pessoas, especialmente estudantes, escritores e professores que, para ser franco, raramente programa para viver ou diariamente para loops também pode ser algo com o qual não está acostumado e que induziu muita carga cognitiva nos primeiros encontros. Esse é um aspecto problemático, porque sempre há uma curva de aprendizado e evitá-la não será eficaz na conversão de alunos em programadores.
Loops aninhados podem enlouquecer, ou seja, podem acabar aninhados muito profundamente. Se eu percorrer cada continente, depois cada país, depois cada cidade, depois cada loja, depois cada prateleira e cada produto, se for uma lata de feijão através de cada feijão e medir seu tamanho para obter a média, então você pode ver que vai aninhar muito profundamente. Você terá uma pirâmide e muito espaço desperdiçado longe da margem esquerda. Você pode até acabar saindo da página.
Este é um problema que seria mais significativo historicamente onde as telas eram pequenas e de baixa resolução. Nesses casos, mesmo alguns níveis de aninhamento poderiam realmente ocupar muito espaço. Hoje, essa é uma preocupação menor, em que o limite é mais alto, embora ainda possa apresentar um problema se houver aninhamento suficiente.
Relacionado é o argumento da estética. Muitas pessoas não acham aninhadas para loops esteticamente agradáveis, em contraste com layouts com alinhamento mais consistente, isso pode ou não estar relacionado ao que as pessoas estão acostumadas, rastreamento ocular e outras preocupações. No entanto, é problemático, pois tende a se auto-reforçar e, finalmente, pode dificultar a leitura do código, pois quebra um bloco de código e encapsula loops atrás de abstrações, como funções, também corre o risco de quebrar o mapeamento do código para o fluxo de execução.
Há uma tendência natural para o que as pessoas estão acostumadas. Se você estiver programando algo da maneira mais simples, a probabilidade de não precisar de aninhamento é maior, a probabilidade de precisar de um nível diminui em uma ordem de magnitude, a probabilidade de outro nível diminui novamente. A frequência diminuindo e, essencialmente, significando que quanto mais profundo o ninho, menos treinados os sentidos humanos são para antecipá-lo.
Relacionado a isso é que, em qualquer construção complexa, na qual um loop aninhado pode ser considerado, você deve sempre perguntar: a solução mais simples possível, pois há potencial para uma solução perdida que precisa de menos loops. A ironia é que uma solução aninhada costuma ser a maneira mais simples de produzir algo que funcione com a quantidade mínima de esforço, complexidade e carga cognitiva. Geralmente, é natural aninhar-se em loops. Se você considerar, por exemplo, uma das respostas acima, em que a maneira mais rápida que um loop for aninhado também é muito mais complexa e consiste em significativamente mais código.
É necessário muito cuidado, pois muitas vezes é possível abstrair os loops ou achatá-los, mas o resultado final acaba sendo uma cura pior do que a doença, principalmente se você não estiver, por exemplo, recebendo um aprimoramento de desempenho mensurável e significativo do esforço.
É muito comum as pessoas experimentarem problemas de desempenho frequentemente associados a loops que estão dizendo ao computador para repetir uma ação muitas vezes e, inerentemente, frequentemente estão envolvidos em gargalos de desempenho. Infelizmente, as respostas a isso podem ser muito superficiais. Torna-se comum que as pessoas vejam um loop e vejam um problema de desempenho onde não há nenhum e depois ocultem o loop da vista, sem nenhum efeito real. O código "parece" rápido, mas o coloca na estrada, aciona a ignição, pisca no acelerador e dá uma olhada no velocímetro e você pode achar que ele ainda é tão rápido quanto uma velhinha andando em seu zimmer.
Esse tipo de ocultação é semelhante a se você tiver dez ladrões no seu caminho. Se, em vez de seguir um caminho direto para onde você deseja ir, você o organizar de forma que haja um assaltante atrás de cada esquina, isso dará a ilusão de que, ao iniciar sua jornada, não haverá assaltantes. Fora da vista, longe da mente. você ainda será assaltado dez vezes, mas agora não verá isso chegando.
A resposta para sua pergunta é que são as duas coisas, mas nenhuma das preocupações é absoluta. Eles são inteiramente subjetivos ou apenas contextualmente objetivos. Infelizmente, às vezes, a opinião inteiramente subjetiva ou melhor, tem precedentes e domina.
Como regra geral, se precisar de um loop aninhado ou parecer o próximo passo óbvio, é melhor não deliberar e simplesmente fazê-lo. No entanto, se houver alguma dúvida, deve ser revisado posteriormente.
Outra regra prática é que você deve sempre verificar a cardinalidade e se perguntar se esse loop será um problema. No meu exemplo anterior, passei pelas cidades. Para os testes, posso passar por apenas dez cidades, mas qual é o número máximo razoável de cidades que se pode esperar no uso no mundo real? Eu poderia então multiplicar o mesmo para os continentes. É uma regra prática sempre considerar com loops, especialmente que iteram uma quantidade dinâmica (variável) de vezes o que isso pode traduzir para baixo da linha.
Independentemente, sempre faça o que funciona primeiro. Da maneira que você vê uma oportunidade de otimização, você pode comparar sua solução otimizada com a mais fácil de começar a trabalhar e confirmar que ela produziu os benefícios esperados. Você também pode gastar muito tempo otimizando prematuramente antes que as medições sejam realizadas, o que leva ao YAGNI ou a muito desperdício de tempo e prazos perdidos.