Como posso encontrar as palavras mais longas na string e retorná-las (excluindo duplicatas) junto com o comprimento máximo?

8

Eu sei como posso encontrar a palavra mais longa em uma string. Por exemplo, este código aqui. Mas aqui o problema é que a palavra "bbbbbb" é encontrada porque ele é a PRIMEIRA PALAVRA MAIS LONGA DA string, depois disso, com 6 caracteres, também temos a palavra "saltou". Minha pergunta é como posso encontrar neste caso e a palavra "saltou", então todos eles não são apenas o primeiro.

UPDATE: quero uma lista exclusiva, portanto, apenas uma de cada palavras

function longestWord(sentence) {
  sentence = sentence.split(' ');

  let theWord = sentence[0];
  var longest = 0;
  for (let i = 0; i < sentence.length; i++) {
    if (sentence[i] != "") {
      if (sentence[i].length > theWord.length) {
        longest = sentence[i].length;
        theWord = sentence[i];
      }
    }
  }
  return {
    length: longest,
    actuallWord: theWord
  }
}
console.log(longestWord("The quick brown as bbbbbb fox jumped over the bbbbbb lazy dog"));

Trajce12
fonte
Tente sentence.filter(w => w.length === longest)obter uma matriz de palavras com esse comprimento.
Rafi
Você pode tentar criar uma matriz para conter as palavras mais longas adicionadas. Em seguida, você pode usar filter () ou map () para avaliar o comprimento e adicionar à matriz.
CoderLee
Agora você tem duas respostas com palavras únicas: Yevhen's e FZs
mplungjan

Respostas:

9

function longestWord(sentence) {
  // First we divide the sentence into words
  var words = sentence.split(' ');
  
  // We then get the length by getting the maximun value of the length of each word
  var length = Math.max(...words.map(a=>a.length));
  return {
    length: length,
    // Finally we filter our words array returning only those of with the same length we previously calculated
    words: words.filter(i => i.length == length)
  }
}
console.log(longestWord("The quick brown as bbbbbb fox jumped over the lazy dog"));

Luis felipe De jesus Munoz
fonte
Bom para obter o comprimento em uma declaração. Preciso de mais porque .sort não retorna a matriz
mplungjan
3
@LuisfelipeDejesusMunoz Por que não adicionar uma explicação? É bom para outros leitores que encontrarem essa resposta. Além do OP.
CoderLee
@YevgenGorbunkov Sua solução também é ótima. Obrigado companheiro
Trajce12
A solução acima não pula palavras duplicadas e o algoritmo que está sendo implementado não é o ideal, pois requer desnecessariamente 2 passagens pela matriz, enquanto a abordagem de passagem única pode obter um desempenho 15% melhor, mesmo para uma sequência de teste tão curta.
Yevgen Gorbunkov
@YevgenGorbunkov Você está certo sobre desempenho, mas não tenho certeza se o OP queria obter palavras únicas (essa parte foi editada na pergunta por outras pessoas )
FZs
2

Você pode adotar uma abordagem de loop único e verificar a extensão de cada palavra com o comprimento dos acumuladores do primeiro item.

function longestWords(words) {
    return words
        .split(/\s+/)
        .reduce((accu, word) => {
            if (!accu[0] || accu[0].length < word.length) return [word];
            if (accu[0].length === word.length) accu.push(word);
            return accu;
        }, []);
}

console.log(longestWords("The quick brown as bbbbbb fox jumped over the lazy dog"));

Nina Scholz
fonte
@mplungjan: Interessante como estilos diferentes atraem pessoas diferentes. Acho essa uma das respostas mais fáceis de ler. Claro que talvez seja porque é semelhante à resposta que escrevi ... mas não publiquei porque Nina me venceu.
Scott Sauyet
2

Você pode fazer isso com Array.prototype.reduce()uma única passagem pela matriz (sem loop extra para calcular o comprimento máximo).

A idéia é redefinir a matriz resultante com uma única palavra, uma vez que seu comprimento exceda os que foram inseridos antes ou acrescentados se a palavra atual tiver o mesmo tamanho ou simplesmente passar de outra forma:

const src = 'The quick brown as bbbbbb fox jumped over the jumped lazy dog',

      result = src.split(' ')
                  .reduce((res, word, idx) => {
                    if(!idx || word.length > res.length)
                        res = {length: word.length, words:new Set([word])}
                    else if(word.length == res.length)
                        res.words.add(word)
                    return res
                  }, {})

console.log({result: result.length, words: [...result.words]})
.as-console-wrapper {min-height:100%}

Yevgen Gorbunkov
fonte
É uma virtude permitir que um noob também entenda o que está acontecendo :)
mplungjan
Eu diria que este stackoverflow.com/a/60153437/295783 é mais legível. Algum comentário?
mplungjan
3
Ternários aninhados são hediondos e perigosos. Sua busca por soluções de linha única fará o codificador depois que você se odeia muito :)
mplungjan
Acho que reduzir não é muito bom para atualizar vários valores juntos (nesse caso, lengthe words).
Gershom
1

Você pode fazer isso reduzindo a sentencematriz.

A vantagem dessa abordagem é que ela faz um loop na matriz apenas uma vez:

function longestWords(sentence) {
  return sentence.split(' ').reduce((output, word) => {
    if (word.length > output.length) {
      output.words = [word]
      output.length = word.length
    } else if (word.length === output.length) {
      output.words.push(word)
    }
    return output
  }, { length: 0, words: [] })
}
console.log(longestWords("The quick brown as bbbbbb fox jumped over the lazy dog"));

Ou, se você quiser filtrar palavras duplicadas, retorne um Set:

function longestWords(sentence) {
  return sentence.split(' ').reduce((output, word) => {
    if (word.length > output.length) {
      output.words.clear()
      output.length = word.length
    } 
    if (word.length >= output.length) {
      output.words.add(word)
    }
    return output
  }, { length: 0, words: new Set })
}
const words = longestWords("The quick brown as bbbbbb fox jumped over the jumped lazy dog")
console.log(words.length);
console.log(Array.from(words.words)) //Just to make StackSnippets console show the Set's entries

FZs
fonte
Esta é a redução mais legível publicada até agora
mplungjan 10/02
Só pode votar uma vez. Grandes exemplos
mplungjan
0

O que você pode fazer é verificar se o comprimento da palavra é maior ou igual ao comprimento do primeiro item da matriz (Todos os itens da matriz devem ter o mesmo comprimento).

Nesse caso, verifique se é maior. Se isso for verdade, defina a matriz com essa palavra, porque você encontrou uma palavra que era maior que as palavras da matriz. Caso contrário, adicione-o à matriz de palavras que têm o maior tamanho.

function longestWord(sentence) {
  sentence = sentence.split(' ');
  let theWord = sentence[0];
  var longest = 0;
  for (let i = 0; i < sentence.length; i++) {
    if (sentence[i] != "") {
      if (sentence[i].length >= theWord[0].length) {
        if (sentence[i].length > theWord[0].length) {
          longest = sentence[i].length;
          theWord = [sentence[i]];
        } else {
          theWord.push(sentence[i])
        }
      }
    }
  }
  return {
    length: longest,
    actuallWord: theWord
  }
}
console.log(longestWord("The quick brown as bbbbbb fox jumped over the lazy dog"));

JSScratchDouble
fonte
0

Também pode ser feito em uma única redução.
Iniciado com o objeto.

function longestWord(words) {
  return words
    .split(/\s+/)
    .reduce((acc, word) => {
  	if(word.length > acc.length) {
  		acc.length = word.length;
  		acc.words = [word];
  	}
  	else if (word.length === acc.length) {
  		acc.words.push(word);
  	}
  	return acc;
  }, {length:0, words:[]});
}

console.log(longestWord("The quick brown as bbbbbb fox jumped over the lazy dog"));

LukStorms
fonte
0

Essa abordagem não tem uma complexidade de tempo melhor do que as melhores respostas aqui, mas possui melhores coeficientes. (Ele apenas percorre a matriz de palavras uma vez, nenhuma função é chamada, exceto Array.prototype.push).

let allLongestItems = items => {
  let longest = [];
  let length = 0;
  for (let item of items) {
    let len = item.length;
    if (len === length) longest.push(item)
    else if (len > length) { longest = [ item ]; length = len; }
  }
  return { items: longest, length };
};

let str = 'The quick brown as bbbbbb fox jumped over the lazy dog';
console.log(allLongestItems(str.split(' ')));

Gershom
fonte