Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

Como comparar e reverter strings do próprio array e retirar do array

Minha dúvida é a seguinte, ao receber um array de strings tenho que comparar string, no caso a palavra, e invertendo ela, se ela for igual a uma palavra que já existe no array, ele irá tirar as palavras repetidas do array e devolver um array sem elas e em ordem crescente, por exemplo:

['code', 'doce', 'ecod', 'report', 'frame', 'amor', 'repo', 'roma']

Assim ele irá retornar então:

['code', 'frame', 'repo', 'report']

Assim, pelo que sei tenho que primeiro verificar as strings desse array comparando todas com uma a uma verificando se são iguais ou não ao inverso das strings do array, depois se forem iguais, retirar elas do array, e por fim colocar o array em ordem crescente ou seja em ordem alfabética.

Eu não consegui realizar essa comparação uma a uma, a única coisa que consegui fazer foi retirar strings que são iguais da seguinte forma:

array = ["A", "B", "C", "B", "A", "D", "E"]
novo_array = array.select{ |e| array.count(e) <= 1 }.uniq
p novo_array

#Resultado = ["C", "D", "E"]

Como posso resolver esse problema?

8 respostas

Oi Fagner tudo bem?

Dá uma olhada nesse código que faz o Bubble Sort

array=['code', 'doce', 'ecod', 'report', 'frame', 'amor', 'repo', 'roma']
def bubble_sort(array)
  n = array.length
  loop do
    swapped = false

    (n-1).times do |i|
      if array[i] > array[i+1]
        array[i], array[i+1] = array[i+1], array[i]
        swapped = true
      end
    end

    break if not swapped
  end

  array
end

bubble_sort(array)

Espero ter ajudado!!!

Olá André, tudo jóia.

Bacana esse algorítimo, já tinha ouvido falar do bubble sort, mas como funciona? Eu entendi parte do código mas não todo, acho que por conta dos métodos ruby. Eu entendi que guarda o tamanho do array em n e inicia o loop, esse loop é a mesma coisa que o while? Depois atribuiu false a variável swapped, dae entra no (n-1).times do |i|, isso é equivalente a um for? Depois entra no if comparando se a posição atual for maior que a posição posterior, então ele vai fazer array[i], array[i+1] = array[i+1], array[i], que não entendi muito bem, e o swapped muda pra true inidcando que foi alterado alguma posição e então tem outro if que se o swapped não for falso, ele encerra e sai desse laço e no fim retorna o array. Poderia me explicar melhor?

Outra questão é que esse método só resolve parte do problema. O grande problema dessa questão é comparar os valores do array, no caso as strings amor e roma, e doce e ecod, ele tem que comparar avaliando que o inverso de amor é roma e são iguais ou vice-versa, mas o importante ele tem que constatar que são iguais, assim como doce e ecod, são iguais , pois o inverso de ecod é doce ou o inverso de ecod é doce que é igual a que já existe que tbm é doce. ou seja ele tem que avaliar as strings em que se o inverso dela for igual ela vai reverter essas strings, e ficará strings iguais dentro do array, e com strings iguais, ele irá retirar essas strings e sobrará o array sem essas strings duplicadas. exemplo:

['code', 'doce', 'ecod', 'report', 'frame', 'amor', 'repo', 'roma']
# aqui ele verificará se os valores invertidos de cada string são iguais as strings passada

Caso tenham strings iguais ele irá então reverter essas strings que ele verificou que são iguais. OBS: Isso na minha maneira de pensar, pois se tiver como já retirá-las assim que se verifica que são iguais, melhor. Mas de qualquer forma penso eu que terar que compará-las.

Então depois de reverter as strings iguais, o array ficará assim:

['code', 'doce', 'doce', 'report', 'frame', 'amor', 'repo', 'amor']

Depois de reverter as strings iguais, terá então que retirá-las, que no caso pode-se usar o código que informei e o array ficará assim:

['code', 'report', 'frame', 'repo']

Por fim, aí sim vem o método bubble_sort que colocará agora o array com as strings já retiradas em ordem alfabética, que ficará assim:

['code', 'frame', 'repo', 'report']

Agora que vem a grande dúvida, como comparo cada string do próprio array e as identifico? Creio que identificando eu possa manipular essa string passando a posição em que ela foi identificada, fazendo a reversão e então gerando um array novo com essas strings revertidas e assim retirar as que estão iguais, no entanto como comparar as strings dentro do array ou até o próprio array?

O swapped é para avisar o programa que foi feito uma troca e é para sair desse número e ir para o próximo. Porque no bubble sort só uma troca é feita por passagem. Tipo o bubble sort é o pior dos algoritimos, só mostrei por fins didáticos mesmo.

O problema do seu código é como saber quem é o correto, doce ou ecod, e também o que fazer quando as duas palavras são corretas como amor e roma. Quem deverá ser invertido?

E para iterar cada caracter de uma string faça assim

 palavra="paralelepipedo"

palavra.each_char do |caracter|

   puts caracter

end 
solução!

Se eu entendi bem o problema, o que você pode fazer é criar um segundo array com todas as palavras do primeiro invertidas e subtrair do primeiro o segundo.

Então se temos um array com ['code', 'doce', 'ecod'] se invertemos esse array termos ['edoc', 'ecod', 'doce'] e o primeiro array menos o segundo remove as duplicatas do primeiro array sobrando só ['code'].

Segue um exemplo:

array = ['code', 'doce', 'ecod', 'report', 'frame', 'amor', 'repo', 'roma']
# essa linha é a mesma que array.map { |word| word.reverse }
inverted_array = array.map(&:reverse)
# => ["edoc", "ecod", "doce", "troper", "emarf", "roma", "oper", "amor"]
# sort no final pra ficar em ordem alfabética
(array - inverted_array).sort
#  => ["code", "frame", "repo", "report"]

É isso mesmo?

Opa, olá Henrique. Nossa era isso mesmo... Não pensava que seria tão simples. O que o método map faz? Não entendi muito bem tbm a função do parâmetro &:. Não sabia que podia subtrair ou somar arrays assim de forma direta, ele soma conforme união e subtrai conforme intercessão, retirando ela não é isso?

No mais é isso mesmo que tinha que fazer, vlw Henrique. Obrigado tbm ao André, aprendi mais sobre o método sort e se adequou para resolver outro problema.

Dá pra resolver esse problema usando vários algoritmos, como você viu com o André.

A solução que eu propus usa Teoria dos Conjuntos que é uma parte que permeia diversos algoritmos.

Respondendo sua dúvida você pode subtrair o array pra criar a diferença entre os dois.

  • Interseção seria: array1 & array2
  • União seria: array1 | array2
# Números que aparecem nos dois Arrays: Interseção
[1, 2, 3] & [1, 2]
# => [1, 2]

# Todos os números dos dois Arrays: União
[1, 2, 3] | [1, 2]
# => [1, 2, 3] 

# Números presentes no primeiro que não existem no segundo: Diferença
[1, 2, 3] - [1, 2]
# => [3] 

A diferença foi usada porque o resultado que você queria era algo que não é apresentado em um dos dois Arrays.

Então ao criar um segundo Array com as palavras invertidas e retirar seu resultado do primeiro só sobra os campos que não existem no segundo é a diferença entre os dois mas se baseando no Array da esquerda da conta.

Outra dica é que o Matz (criador do Ruby) queria que a linguagem fosse amiga do programador então tem método declarado pra muita coisa, é sempre bom consultar a documentação.

ps.: Sobre o método map ele faz exatamente o que seu nome sugere, mapeia os elementos para a condição, um exemplo mais básico

[1, 2, 3, 4, 5, 6].map { |element| element.odd? }
# => [true, false, true, false, true, false]

O Array [1, 2, 3, 4, 5, 6] foi mapeado para um segundo array que guarda se o número daquela casa é ou não impar. Se você quiser guardar o resultado tem que salvar numa variável como fizemos anteriormente.

Aí quanto aos : é uma sintaxe mais "simples" do map (e outros métodos), o Ruby já espera que você queira mapear cada elemento pra um método com ela então quando fazemos [1, 2, 3, 4, 5, 6].map(&:odd?) estamos fazendo a mesma chamada de cima mas de uma forma mais prática, você pode ler mais aqui:

https://www.brianstorti.com/understanding-ruby-idiom-map-with-symbol/

Mas o "por trás dos panos" dela é um pouquinho complexa se você está começando com Ruby, então você pode usar a sintaxe mais lógica que é a primeira.

Obrigado Henrique, entendi agora, ajudou bastante mesmo, vlw, aprendendo cada vez mais com essa linguagem!!!

Disponha e bons estudos!!!