Adicionar novos elementos em um array
Olá galera!
Estou tentando adicionar novos elementos em um array.
Entretanto, se o elemento a ser adicionado no array já existir, gostaria que a função procurasse outro elemento para adicionar, e que a mesma só fosse encerrada após conseguir adicionar um elemento novo.
Eu tenho dois objetos:
Na função "addPlayedMaps(stage)" a seguir, eu quero adicionar um único valor de allMaps.Stage1 para o playedMaps.Stage1.
Então eu executo a função 5 vezes, para que todos os valores de allMaps.Stage1 preencham o playedMaps.Stage1.
Entretanto, nem sempre eu consigo adicionar 5 valores. As vezes o console log me dá 4 valores ou 3...
O que tem de errado no meu loop for() ?
for(let i = getRandomInt(5, 9); // i é igual a qualquer um dos números: 5, 6, 7, 8, 9.
playedMaps[stage].indexOf(i) === -1; // Se i não existir no objeto(se o index dele for -1) playedMaps[stage], então executa a declaração.
i = getRandomInt(5, 9) ){ // Caso i já exista no objeto, fazer o sorteio de novo entre os números 5 a 9.
playedMaps[stage].push(i); // Declaração sendo executada e adicionando i ao objeto.
}
Estou tentando adicionar novos elementos em um array.
Entretanto, se o elemento a ser adicionado no array já existir, gostaria que a função procurasse outro elemento para adicionar, e que a mesma só fosse encerrada após conseguir adicionar um elemento novo.
Eu tenho dois objetos:
const allMaps = { Stage0: null, Stage1: [5,6,7,8,9], Stage2: [11,12,13,14,15], Stage3: [17,18,19,20,21], Stage4: [23,24,25,26,27], Stage5: [29,30,31,32,33], Stage6: [35,36,37,38,39] } let playedMaps = { Stage0: null, Stage1: [], Stage2: [], Stage3: [], Stage4: [], Stage5: [], Stage6: [] }
Na função "addPlayedMaps(stage)" a seguir, eu quero adicionar um único valor de allMaps.Stage1 para o playedMaps.Stage1.
function getRandomInt(min, max) { min = Math.ceil(min); max = Math.floor(max + 1); return Math.floor(Math.random() * (max - min)) + min; }; function addPlayedMaps(stage){ for(let i = getRandomInt(5, 9); playedMaps[stage].indexOf(i) === -1; i = getRandomInt(5, 9) ){ playedMaps[stage].push(i); } return playedMaps; }; addPlayedMaps("Stage1"); addPlayedMaps("Stage1"); addPlayedMaps("Stage1"); addPlayedMaps("Stage1"); addPlayedMaps("Stage1"); console.log(playedMaps["Stage1"].sort());
Então eu executo a função 5 vezes, para que todos os valores de allMaps.Stage1 preencham o playedMaps.Stage1.
addPlayedMaps("Stage1"); addPlayedMaps("Stage1"); addPlayedMaps("Stage1"); addPlayedMaps("Stage1"); addPlayedMaps("Stage1"); console.log(playedMaps["Stage1"].sort());
Entretanto, nem sempre eu consigo adicionar 5 valores. As vezes o console log me dá 4 valores ou 3...
O que tem de errado no meu loop for() ?
for(let i = getRandomInt(5, 9); // i é igual a qualquer um dos números: 5, 6, 7, 8, 9.
playedMaps[stage].indexOf(i) === -1; // Se i não existir no objeto(se o index dele for -1) playedMaps[stage], então executa a declaração.
i = getRandomInt(5, 9) ){ // Caso i já exista no objeto, fazer o sorteio de novo entre os números 5 a 9.
playedMaps[stage].push(i); // Declaração sendo executada e adicionando i ao objeto.
}
Eliaquim Nascimento
Curtidas 1
Melhor post
Stella Oliveira
12/03/2020
O seu problema está no loop. Seu loop foi criado da maneira errada, pois você está reatribuindo sua variável "i" no fim do statement.
Um outro problema da sua função é que ela pega um intervalo de números ( motivo pelo qual eu recomendo usar um array de strings de primeira pra facilitar o entendimento )
Quando você faz getRandomInt(5, 9), isso se resolve pro Stage1, mas não resolve para o stage2, que vai de 11 a 15, obrigando você a escrever dois loops diferentes, não possibilitando você reutilizar sua função para outros stages.
Outro problema do seu loop é que ele não leva em consideração todos os estágios de allMaps, causando uma coincidência de valores.
Abaixo eu te proponho uma funcao que você pode reutilizar para qualquer stage.
Ela vai adiciona um único mapa no array toda vez que ela for chamada e vai validar se o array já está cheio também.
Dá uma olhadinha
Um outro problema da sua função é que ela pega um intervalo de números ( motivo pelo qual eu recomendo usar um array de strings de primeira pra facilitar o entendimento )
Quando você faz getRandomInt(5, 9), isso se resolve pro Stage1, mas não resolve para o stage2, que vai de 11 a 15, obrigando você a escrever dois loops diferentes, não possibilitando você reutilizar sua função para outros stages.
Outro problema do seu loop é que ele não leva em consideração todos os estágios de allMaps, causando uma coincidência de valores.
Abaixo eu te proponho uma funcao que você pode reutilizar para qualquer stage.
Ela vai adiciona um único mapa no array toda vez que ela for chamada e vai validar se o array já está cheio também.
Dá uma olhadinha
function addPlayedMaps (stage) { const allMapsLenght = (allMaps[stage].length - 1) const randomInt = getRandomInt(0, allMapsLenght) if (playedMaps[stage].length >= allMaps[stage].length) { return } const hasPlayed = playedMaps[stage].some(mapItem => { if (mapItem === allMaps[stage][randomInt]) { return true } }) if (!hasPlayed && !!allMaps[stage][randomInt]) { playedMaps[stage].push(allMaps[stage][randomInt]) } if (hasPlayed) { addPlayedMaps(stage) } }
GOSTEI 1
Mais Respostas
Eliaquim Nascimento
12/03/2020
Seu loop foi criado da maneira errada, pois você está reatribuindo sua variável "i" no fim do statement.
Hmm... Não imaginaria que fosse isso... achei que reatribuir o valor ali, funcionasse como i++ ou i--, que no meu caso seria gerar um outro valor aleatório de 5 a 9.
Nesse caso, eu poderia gerar esse valor novamente no loop, dentro do corpo(declaração)?
for(let i = getRandomInt(5, 9); playedMaps[stage].indexOf(i) === -1; ){ playedMaps[stage].push(i); i = getRandomInt(5, 9) // Aqui? }
Um outro problema da sua função é que ela pega um intervalo de números ( motivo pelo qual eu recomendo usar um array de strings de primeira pra facilitar o entendimento )
Array de strings de primeira?
Tipo assim:
ler arr = [ ["5","6","7","8","9"], ["11","12","13","14","15"] ... ]
Quando você faz getRandomInt(5, 9), isso se resolve pro Stage1, mas não resolve para o stage2, que vai de 11 a 15, obrigando você a escrever dois loops diferentes, não possibilitando você reutilizar sua função para outros stages.
Sim, verdade! É que eu tava querendo primeiro fazer funcionar hahaha
Eu testei a função e funcionou direitinho!!! Ficou fera, obrigadão mesmo!
if (!hasPlayed && !!allMaps[stage][randomInt]) {
playedMaps[stage].push(allMaps[stage][randomInt])
}
playedMaps[stage].push(allMaps[stage][randomInt])
}
Usar o "randomInt aqui > allMaps[stage][randomInt] < foi um mindblowing pra mim xD
Valeu mesmo.
Eu só não entendi essa condição: "!!allMaps[stage][randomInt]", dois pontos de exclamação? Duas negativas? Para que serve esses dois?
GOSTEI 0
Stella Oliveira
12/03/2020
Isso serve apenas pra forçar um true/false.
No javascript:
É só pra garantir que vai funcionar
Entretanto, o seu código ainda tem um problema. Se um dos seus arrays contiver um número 0, ele vai dar errado. Por que em JS, o valor 0 é tratado como false. Sei que sua questão tem a ver com aprender, mas vale atentar que:
No javascript:
//Se você fizer const obj = { foo: "bar" } if (obj.foo) // isso é true por que o JS avalia ele como um objeto que existe if (!obj.foo) // isso é false por que o javascript converte para booleano if (!!obj.foo) // eu estou convertendo para um booleano e invertendo o valor dele !obj.foo == false, !!obj.foo == true
É só pra garantir que vai funcionar
Entretanto, o seu código ainda tem um problema. Se um dos seus arrays contiver um número 0, ele vai dar errado. Por que em JS, o valor 0 é tratado como false. Sei que sua questão tem a ver com aprender, mas vale atentar que:
const allMaps = { Stage0: null, Stage1: [0, 5,6,7,8,9] // esse 0 vai automaticamente dar false }
GOSTEI 1
Eliaquim Nascimento
12/03/2020
Haaa sim...
Entendi o lance do "!!".
Sim, eu fiquei ciente que o número 0 pode dar false, depois de entender a explicação.
Esses números são o ID de cada mapa, e os Id's são sempre maiores que 0, então não corro esse risco.
Muito obrigado pela ajuda, problema resolvido! ^^
Entendi o lance do "!!".
Sim, eu fiquei ciente que o número 0 pode dar false, depois de entender a explicação.
Esses números são o ID de cada mapa, e os Id's são sempre maiores que 0, então não corro esse risco.
Muito obrigado pela ajuda, problema resolvido! ^^
GOSTEI 1
Stella Oliveira
12/03/2020
Cara, agora que vi que não respondi outras perguntas suas:
Você citou
Array de strings de primeira?
Tipo assim:
ler arr = [ ["5","6","7","8","9"], ["11","12","13","14","15"] ... ]
Eu queria dizer strings mesmo. Acho que nesse ponto você já sabe, mas vale lembrar que o JS é uma linguagem que força tipagem
Então usar números em comparações exatas sempre é meio perigoso. Eu, particularmente, usaria assim ( já aviso que entendo o problema de dar nomes assim, uma hora a criatividade acaba haha ):
Mas eu digo isso mais pelo contexto. Na hora de programar, é mais fácil eu pensar que eu to comparando a "dust2" dos que já joguei com a "dust2" de allMaps. Eu falei isso mais por facilitar seu entendimento do seu código, mas depois que você me disse que recebe um array de ids, eu meio que entendi qual foi a intenção :)
Você também mencionou
Você até poderia fazer o que você propôs ( não sei dizer se daria certo por que eu mesmo não testei ), mas eu te colocaria o seguinte argumento:
Escrever o código daquela maneira não é muito comum, portanto deixa seu código mais difícil de entender pra um futuro colega e até mesmo pra você daqui um tempo. Eu, inclusive, te faço uma proposta: volta nessa questão que você abriu daqui 3 meses e dá uma lida nela. Eu te garanto que vai ser meio difícil de você entender o código que você propôs, por que nele falta clareza de intenção. Algo que é bastante discutido no livro Clean Code do Martin Fowler ( super recomendo, inclusive )
:D
Você citou
Array de strings de primeira?
Tipo assim:
ler arr = [ ["5","6","7","8","9"], ["11","12","13","14","15"] ... ]
Eu queria dizer strings mesmo. Acho que nesse ponto você já sabe, mas vale lembrar que o JS é uma linguagem que força tipagem
if (5 == "5") // isso é true
Então usar números em comparações exatas sempre é meio perigoso. Eu, particularmente, usaria assim ( já aviso que entendo o problema de dar nomes assim, uma hora a criatividade acaba haha ):
let arr = ["dust2", "poolday"] // e por ai vai
Mas eu digo isso mais pelo contexto. Na hora de programar, é mais fácil eu pensar que eu to comparando a "dust2" dos que já joguei com a "dust2" de allMaps. Eu falei isso mais por facilitar seu entendimento do seu código, mas depois que você me disse que recebe um array de ids, eu meio que entendi qual foi a intenção :)
Você também mencionou
Nesse caso, eu poderia gerar esse valor novamente no loop, dentro do corpo(declaração)?
Você até poderia fazer o que você propôs ( não sei dizer se daria certo por que eu mesmo não testei ), mas eu te colocaria o seguinte argumento:
Escrever o código daquela maneira não é muito comum, portanto deixa seu código mais difícil de entender pra um futuro colega e até mesmo pra você daqui um tempo. Eu, inclusive, te faço uma proposta: volta nessa questão que você abriu daqui 3 meses e dá uma lida nela. Eu te garanto que vai ser meio difícil de você entender o código que você propôs, por que nele falta clareza de intenção. Algo que é bastante discutido no livro Clean Code do Martin Fowler ( super recomendo, inclusive )
:D
GOSTEI 1
Stella Oliveira
12/03/2020
Leituras adicionais que eu mesmo li e recomendo sempre que posso
- https://www.amazon.com.br/C%C3%B3digo-limpo-Robert-C-Martin/dp/8576082675/ref=asc_df_8576082675/?tag=googleshopp00-20&linkCode=df0&hvadid=379792215563&hvpos=&hvnetw=g&hvrand=4226168958323978339&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1001566&hvtargid=pla-398225630878&psc=1
- https://martinfowler.com/ieeeSoftware/explicit.pdf
- https://medium.com/@kennethreilly/coding-with-intention-d1d61f5add20
- https://novatec.com.br/livros/programador-melhor/
- https://www.amazon.com.br/C%C3%B3digo-limpo-Robert-C-Martin/dp/8576082675/ref=asc_df_8576082675/?tag=googleshopp00-20&linkCode=df0&hvadid=379792215563&hvpos=&hvnetw=g&hvrand=4226168958323978339&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1001566&hvtargid=pla-398225630878&psc=1
- https://martinfowler.com/ieeeSoftware/explicit.pdf
- https://medium.com/@kennethreilly/coding-with-intention-d1d61f5add20
- https://novatec.com.br/livros/programador-melhor/
GOSTEI 1
Eliaquim Nascimento
12/03/2020
Opa!!
Valeu por responder as outras questões!
Eu ia perguntar de novo, mas acabei entendendo depois que mexi na função de novo aqui.
Vou ficar de olho nesses livros, de repente algum deles tem no KindleUnlimited. Obrigado mesmo pelas recomendações, eu acho tantos livros que as vezes não sei qual vale a pena ler devido ao meu tempo. Então sempre bom ter umas recomendações.
acontece a todo momento hahaha
Valeu por responder as outras questões!
Eu ia perguntar de novo, mas acabei entendendo depois que mexi na função de novo aqui.
Vou ficar de olho nesses livros, de repente algum deles tem no KindleUnlimited. Obrigado mesmo pelas recomendações, eu acho tantos livros que as vezes não sei qual vale a pena ler devido ao meu tempo. Então sempre bom ter umas recomendações.
Eu, inclusive, te faço uma proposta: volta nessa questão que você abriu daqui 3 meses e dá uma lida nela. Eu te garanto que vai ser meio difícil de você entender o código
acontece a todo momento hahaha
GOSTEI 0