字母计数 - 如何 return 第一个单词重复字母最多的单词?

Letter Count - How to return the first word with the highest amount of repeating letters?

例如:“今天,是最棒的一天!”应该 return 最大,因为它有 2 个 e(和 2 个 t),而且它在 ever 之前也有 2 个 e。如果没有重复字母的单词return -1。单词将由空格分隔。 输入:“你好苹果派” 输出应该是:“你好” 不明白我的代码有什么问题,如果您认为有更简单、更短的解决方法,我也很乐意听到。在此先感谢您的帮助。

  function LetterCountI(str) { 
    let unique=[... new Set(str)]
    if(unique==str){ 
      return -1}
    
    let arr= str.split(" ") 
    
    let array=arr.map(item=>{ 

    let temparr=item.split("")

      return temparr.reduce((acc,curr)=>{ 
    acc[curr]=acc[curr]? acc[curr]+1:1 
    if(acc[curr]>acc.max){ 
      acc.max=acc[curr]}
return acc},{max:1, word:item})}) 
    
    let amount=1
    let largest=""
    
    for(let item of arr){ 
      if( item.max>amount){ 
        amount=item.max 
        largest=item.word
      }
    } 
    
    return largest
    
   }

从更简单的问题开始,即获取单词中每个字母的出现频率...

// given "sassy", will return { s:3, a:1, y:1 }
function letterFrequency(word) {
  return word.split('').reduce((acc, letter) => {
    if (!acc[letter]) acc[letter] = 0;
    acc[letter]++;
    return acc;
  }, {});
}

获得最大频率的一个简单问题...

// given { s:3, a:1, y:1 }, will return 3
function maxLetterFrequency(word) {
  return Math.max(...Object.values(letterFrequency(word)));
}

另一个按频率对句子排序的简单问题...

// given "She sells seashells by the seashore"
// returns ["seashells", "sells", "seashore", "She", "by", "the"]
function wordsOrderedByMaxLetterFrequency(sentence) {
  let words = sentence.split(' ');
  words.sort((a, b) => {
    return maxLetterFrequency(b) - maxLetterFrequency(a);
  });
  return words;
}

结果数组中的第一个单词就是答案。您可以重新测试该词中的最大频率以确定答案应为 -1。

演示...

// given "sassy", will return { s:3, a:1, y:1 }
function letterFrequency(word) {
  return word.split('').reduce((acc, letter) => {
    if (!acc[letter]) acc[letter] = 0;
    acc[letter]++;
    return acc;
  }, {});
}

// given { s:3, a:1, y:1 }, will return 3
function maxLetterFrequency(word) {
  return Math.max(...Object.values(letterFrequency(word)));
}

// given "She sells seashells by the seashore"
// returns ["seashells", "sells", "seashore", "She", "by", "the"]
function wordsOrderedByMaxLetterFrequency(sentence) {
  let words = sentence.split(' ');
  words.sort((a, b) => {
    return maxLetterFrequency(b) - maxLetterFrequency(a);
  });
  return words;
}

const sentence = "She sells seashells by the seashore";
const sorted = wordsOrderedByMaxLetterFrequency(sentence);
console.log(sorted);
console.log('best word:', sorted[0]);
console.log('max freq in best word:', maxLetterFrequency(sorted[0]));

坚持 OP 基于 reduce 的方法,我们将提供一个单一功能,其中包含两个特定的嵌套 reduce 任务,负责 1) 聚合句子的单词特定统计信息和 2) 字母每个单词的特定统计信息。 这种方法还确保了 ''(建议)或 -1(OP 的要求)的结果,以防只有唯一(不重复)的单词 letters/characters.

function getFirstOccurringWordOfMaximumSameCharacterCount(value) {

  function aggregateCharCountData(wordStats, char, idx, arr) {
    const { charStats } = wordStats;

    // aggregate character specific array.
    (charStats[char] ??= []).push(char);

    if (idx >= (arr.length - 1)) {
      // console.log({ charStats });

      // aggregate maximum character count data
      // at the end of the last character reduce step.
      const maxCharList = Object
        .values(charStats)
        .sort((aCharList, bCharList) =>
          bCharList.length - aCharList.length
        )[0];

      wordStats.maxCharCount = maxCharList.length;
      wordStats.maxCountChar = maxCharList[0];
    }
    return wordStats;
  }
  function aggregateWordSpecificCharCountData(collector, word, idx, arr) {
    const { statistics } = collector;

    statistics.push(
      word
        .split('')
        .reduce(aggregateCharCountData, { word, charStats: {} })
    );
    if (idx >= (arr.length - 1)) {

      // find the first occurring word of maximum same character count
      // at the end of the last word reduce step.
      const wordStats = statistics
        .sort((aWordStats, bWordStats) =>
          bWordStats.maxCharCount - aWordStats.maxCharCount
        )[0];
      // console.log({ statistics });

      collector.result = (wordStats.maxCharCount >= 2)
        ? wordStats.word
        : ''; // : -1;
    }
    return collector;
  }

  const {

    // statistics,
    result,

  } = String(value)
    .split(/\s+/)

    .reduce(aggregateWordSpecificCharCountData, {
      statistics: [],
      result: '',
    });
  // console.log({ statistics });

  return result;
}

console.log([

  'Today is the day.',                  // ''
  'Today, is the greatest day ever!',   // 'greatest'
  'Hello Apple Pie',                    // 'Hello'
  'She sells seashells by the seashore' // 'seashells'

].map(getFirstOccurringWordOfMaximumSameCharacterCount));
.as-console-wrapper { min-height: 100%!important; top: 0; }

我最初的方法是分离出一个 maxBy 函数,该函数接受一个从输入值中提取比较数字的函数和 return 一个从值列表到其中最大值的函数.

然后我们可以编写 letterCount 来计算字符串中各种字母的出现次数,并用一个函数 maxLetterCount 来计算字符串的最大字母数,使用 Math .max 来自 letterCount 的值,并编写我们的主要函数将您的初始字符串拆分为单词,并使用 maxLetterCount 对单词列表调用 maxBy。它可能看起来像这样:

// DO NOT USE -- Doesn't meet all requirements!

const maxBy = (fn) => (xs) => xs .reduce (
  ({m, r}, x) => {const v = fn(x); return v > m ? {m: v, r: x} : {m, r}}, 
  {m: -Infinity}
) .r

const letterCount = ([...cs]) => 
  cs .reduce ((a, c) => {a [c] = (a [c] || 0) + 1; return a}, {})

const maxLetterCount = (cs) => 
  Math .max (... Object .values (letterCount (cs)))

const letterCountI = (s) =>
  maxBy (maxLetterCount) (s .split (/\s+/))

console .log (letterCountI ("Today, is the greatest day ever!"))
console .log (letterCountI ("Hello Apple Pie"))

但是这种方法有一个问题。它没有考虑您的要求,如果没有重复的字母,我们必须 return -1。现在,letterCountI ("Today is the day") 将 return "Today"

此问题的一个解决方法可能涉及将单词与其最大字母数配对,将这些对过滤为仅包含 multiply-occurring 个字母的那些,然后再次对这些对使用 maxBy,最后从获胜的一对中拉出这个词。为了处理 -1 的情况,我们可以在过滤后的列表中插入一个虚拟对,其中 -1 表示单词,-Infinity 表示字母数。如果列表为空,那么我们将选择这个。

这样做可能会导致我们向 maximumBy 添加一些默认行为,目前仅限于数字,但理想情况下应该可以与我们可以使用 < 进行比较的任何东西一起使用。如果我们默认 -Infinity 的下限,但允许覆盖,并将其与空列表的默认值配对,那么我们可能可以通过相当简单的方式完成上述操作。1

但这感觉有点过于复杂了。也许更简单的方法是简单地执行上面的代码,然后测试生成的单词是否有重复的字母。虽然我们可以通过函数跟踪它,但我认为最简单的版本是再次调用 letterCount 。所以这就是我可能会选择编写此函数的方式:

const maxBy = (fn) => (xs) => xs .reduce (
  ({m, r}, x) => {const v = fn(x); return v > m ? {m: v, r: x} : {m, r}}, 
  {m: -Infinity}
) .r

const letterCount = ([...cs]) => 
  cs .reduce ((a, c) => {a [c] = (a [c] || 0) + 1; return a}, {})

const maxLetterCount = (cs) => 
  Math .max (... Object .values (letterCount (cs)))

const letterCountI = (s, target = maxBy (maxLetterCount) (s .split (/\s+/))) =>
  maxLetterCount (target) > 1 ? target : -1

console .log (letterCountI ("Today, is the greatest day ever!"))
console .log (letterCountI ("Hello Apple Pie"))
console .log (letterCountI ("Today, is the day!"))


1 可能看起来像这个(未经测试的)版本:

const maximumBy = (fn, {dfltVal = '', lowBound = -Infinity} = {}) => (xs) => xs .reduce (
  ({m, r}, x) => {const v = fn(x); return v > m ? {m: v, r: x} : {m, r}}, 
  {m: lowBound, r: dfltVal}
) .r