在字符串中计算字符串出现的次数

huangapple go评论73阅读模式
英文:

Count string occurrences in string

问题

我被委托尝试从一个字符串中获取一个字符串的出现次数这是以逗号分隔的学校报告的形式给出的有三种不同的字符串绿色琥珀色红色我必须对它们进行计数并将它们作为报告字符串类型输出如下所示

绿色: 1
琥珀色: 1
红色: 1


从上面的内容中可以看出,它们每个后面都必须有一个新行。

我已经为这些编写了测试用例,并在硬编码正确答案之后,尝试将字符串拆分为数组并尝试迭代它们以计算绿色、琥珀色、红色的出现次数,但一直没有成功。

这是我开始实验之前的内容:

```javascript
function report(str) {
  const arr = str.split(',');
  arr.forEach(el => {
    if (el === "绿色") {
      return 
    } else if (el === "琥珀色" ) {
      return 
    } else {
      return 
    }
  });
}

这是我编写的内容。但它返回未定义:

function report(str) {
  let countGreen = 0;
  let countAmber = 0;
  let countRed = 0;

  let reportCount = `绿色: ${countGreen}\n琥珀色: ${countAmber}\n红色: ${countRed}`

  const arr = str.split(",")

  // 循环遍历项目
  arr.forEach((str) => {

      // 检查字符是否在该位置
      if (str === "绿色") {
        countGreen += 1;
      } else if (str === "琥珀色") {
        countAmber += 1;
      } else {
        countRed += 1
      }
    });
    return reportCount;
}

module.exports = report;

以下是测试:

const report = require('../src/report')

describe('#报告', () => {
  test('返回字符串作为输出', () => {
    expect(typeof report("绿色")).toBe("string")
  })

  describe('可以计算颜色的数量', () => {
    describe('绿色', () => {
      test('计算一个绿色', () => {
        expect(report("绿色")).toBe("绿色: 1")
      })
      test('计算两个绿色', () => {
        expect(report("绿色, 绿色")).toBe("绿色: 2")
      })
    })
    describe('琥珀色', () => {
      test('计算一个琥珀色', () => {
        expect(report("琥珀色")).toBe("琥珀色: 1")
      })
    })
    describe('红色', () => {
      test('计算一个红色', () => {
        expect(report("红色")).toBe("红色: 1")
      })
    })
  })
})

<details>
<summary>英文:</summary>

I&#39;ve been tasked with trying to get the occurrences of a string from a string. This is in the form of school reports given as a comma separated string. There&#39;s three different strings, Green, Amber, Red. I have to count these and output them as a report (of type string) like: 

Green: 1
Amber: 1
Red: 1


As you can tell from the above they have to have a new line after each one. 

I&#39;ve written test cases for these and after I hard coded the right answers I haven&#39;t had any luck with trying to split the string in an array and try to iterate over them to count the occurrences of the Green, Amber, Red. 


This is what I had before I started to experiment:

function report(str) {
const arr = str.split(',');
arr.forEach (el => {
if (el === "Green") {
return
} else if (el === "Amber" ) {
return
} else {
return
}
});
}



This is what I coded. But it comes back as undefined:

function report(str) {
let countGreen = 0;
let countAmber = 0;
let countRed = 0;

let reportCount = Green: ${countGreen}\n Amber: ${countAmber}\n Red: ${countRed}

const arr = str.split(",")

// looping through the items
arr.forEach ((str) => {

  // check if the character is at that position
  if (str === &quot;Green&quot;) {
    countGreen += 1;
  } else if (str === &quot;Amber&quot;) {
    countAmber += 1;
  } else {
    countRed += 1
  }
});
return reportCount;

}

module.exports = report;


Here are the tests:

const report = require('../src/report')

describe('#Report', () => {
test('Returns a string as an output', () => {
expect(typeof report("Green")).toBe("string")
})

describe('can count number of colours', () => {
describe('greens', () => {
test('counts one green', () => {
expect(report("Green")).toBe("Green: 1")
})
test('counts two greens', () => {
expect(report("Green, Green")).toBe("Green: 2")
})
})
describe('ambers', () => {
test('counts one amber', () => {
expect(report("Amber")).toBe("Amber: 1")
})
})
describe('reds', () => {
test('counts one red', () => {
expect(report("Red")).toBe("Red: 1")
})
})
})
})


</details>


# 答案1
**得分**: 0

这是正常的。你在函数开始处创建了一个 reportCount 变量。所有值都是零,所以即使你找到一个,除非在每种颜色的计数之后定义你的答案,否则它将始终显示为零。

<details>
<summary>英文:</summary>

It is normal. You are creating a reportCount at the begginning of the function. All values are at zero, so even if you found one, it will always show zero unless you define your answer after the count of each color.

</details>



# 答案2
**得分**: 0

你的代码看起来很好。@trinkot 唯一想说的是,在 `forEach` 语句之后,就在 `return` 语句之前构建包含计数的最终字符串。

演示 **:** 

```javascript
const inputStr = 'Green,Amber,Amber,Green,Red,Amber,Green,Red,Red,Green,Amber,Amber,Red,Red,Green,Green';

function report(str) {
  let countGreen = 0;
  let countAmber = 0;
  let countRed = 0;
  
  const arr = str.split(",");
  
  // 遍历项目
  arr.forEach((str) => {
    // 检查字符是否在该位置
    if (str.trim() === "Green") {
      countGreen += 1;
    } else if (str.trim() === "Amber") {
      countAmber += 1;
    } else {
      countRed += 1;
    }
  });

  let reportCount = `Green: ${countGreen}\n Amber: ${countAmber}\n Red: ${countRed}`;

  return reportCount;
}

console.log(report(inputStr));

使用 Array.reduce() 方法更优化/紧凑的解决方案 :

const inputStr = 'Green,Amber,Amber,Green,Red,Amber,Green,Red,Red,Green,Amber,Amber,Red,Red,Green,Green';

const arr = inputStr.split(",");
let output = '';

var countsObj = arr.reduce((colorCountObj, currentColor) => {
   colorCountObj[currentColor.trim()] = colorCountObj[currentColor.trim()] + 1 || 1;
   return colorCountObj;
}, {});

Object.entries(countsObj).forEach(entry => {
  output += `${entry.join(': ')}\n`;
});

console.log(output);
英文:

Your code looks good. The only thing which @trinkot trying to say is that construct the final string with the counts after the forEach statement and just before the return statement.

Demo :

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const inputStr = &#39;Green,Amber,Amber,Green,Red,Amber,Green,Red,Red,Green,Amber,Amber,Red,Red,Green,Green&#39;;

function report(str) {
  let countGreen = 0;
  let countAmber = 0;
  let countRed = 0;
  
  const arr = str.split(&quot;,&quot;)

  // looping through the items
  arr.forEach ((str) =&gt; {
    // check if the character is at that position
    if (str.trim() === &quot;Green&quot;) {
      countGreen += 1;
    } else if (str.trim() === &quot;Amber&quot;) {
      countAmber += 1;
    } else {
      countRed += 1
    }
  });

  let reportCount = `Green: ${countGreen}\n Amber: ${countAmber}\n Red: ${countRed}`

  return reportCount;
}

console.log(report(inputStr));

<!-- end snippet -->

More optimal/compact solution by using Array.reduce() method :

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const inputStr = &#39;Green,Amber,Amber,Green,Red,Amber,Green,Red,Red,Green,Amber,Amber,Red,Red,Green,Green&#39;;

const arr = inputStr.split(&quot;,&quot;)
let output = &#39;&#39;

var countsObj = arr.reduce((colorCountObj, currentColor) =&gt; {
   colorCountObj[currentColor.trim()] = colorCountObj[currentColor.trim()] + 1 || 1
   return colorCountObj;
}, {});

Object.entries(countsObj).forEach(entry =&gt; {
  output += `${entry.join(&#39;: &#39;)}\n`
})

console.log(output);

<!-- end snippet -->

答案3

得分: 0

以下是翻译好的部分:

  1. You build the reportCount string before the counts have been done, so it will have only 0 as counts. This should happen near the end of your function when the loop has done its work, and you have the counts.

    • 在计数完成之前,您在函数的开头构建了reportCount字符串,因此计数始终为0。这应该在函数的末尾进行,当循环完成其工作并且您拥有计数时。
  2. The tests show that when a color is not included in the input string, it should not be in the report either. But your string will always report on three colors. You need to check for which colors you have a non-zero count, and only include those colors. That logic is currently missing in your code.

    • 测试表明,如果颜色未包含在输入字符串中,它也不应出现在报告中。但您的字符串始终会报告三种颜色。您需要检查哪些颜色具有非零计数,然后只包括这些颜色。这个逻辑目前在您的代码中缺失。
  3. Your reportCount string adds a space after every line break. This is not what the description said you should do. The only spaces in the output should occur after the colon (:), nowhere else.

    • 您的reportCount字符串在每个换行符后添加了一个空格。这不符合描述中的要求。输出中唯一的空格应该出现在冒号(:)之后,而不是其他地方。
  4. Not a problem, but:

    • 不是问题,但是:
  5. There is code repetition, i.e. your code is doing somewhat the same thing three times, once for every color. You can avoid this by storing the counters as property values of a plain object that is keyed by the names of the colors.

    • 存在代码重复,即您的代码为每种颜色执行了大致相同的操作三次。您可以通过将计数器存储为以颜色名称为键的普通对象的属性值来避免这种重复。

以下是您的代码的修正版本:

function report(str) {
    // 使用对象来避免在每个if语句中重复代码
    const counts = {
        Green: 0,
        Amber: 0,
        Red: 0,
    };

    for (const color of str.split(",")) {
        counts[color.trim()]++; // 计数很容易...
    }

    return Object.entries(counts) // 获取每种颜色及其计数
        .filter(([color, count]) => count) // 过滤掉计数为零的颜色
        .map(([color, count]) => `${color}: ${count}`) // 格式化为字符串
        .join("\n");  // 使用换行符连接
}

// 一些测试:
console.log(report("Green"));
console.log(report("Green, Green"));
console.log(report("Amber"));
console.log(report("Red"));
console.log(report("Red, Green, Red, Amber, Red, Green"));

如果您仍希望使用if语句并且不使用数组方法,可以像这样编写:

function report(str) {
    let countGreen = 0;
    let countAmber = 0;
    let countRed = 0;

    for (let color of str.split(",")) {
        color = color.trim(); // 仅执行一次
        if (color === "Green") {
            countGreen++;
        } else if (color === "Amber") {
            countAmber++;
        } else {
            countRed++;
        }
    }

    let reportCount = ""; // 开始构建...
    if (countGreen) {
        reportCount += "Green: " + countGreen + "\n";
    }
    if (countAmber) {
        reportCount += "Amber: " + countAmber + "\n";
    }
    if (countRed) {
        reportCount += "Red: " + countRed + "\n";
    }
    return reportCount.trim(); // 去掉最后的换行字符
}

// 一些测试:
console.log(report("Green"));
console.log(report("Green, Green"));
console.log(report("Amber"));
console.log(report("Red"));
console.log(report("Red, Green, Red, Amber, Red, Green"));
英文:

There are these issues:

  • You build the reportCount string before the counts have been done, so it will have only 0 as counts. This should happen near the end of your function, when the loop has done its work, and you have the counts.

  • The tests show that when a color is not included in the input string, it should not be in the report either. But your string will always report on three colors. You need to check for which colors you have a non-zero count, and only include those colors. That logic is currently missing in your code.

  • Your reportCount string adds a space after every line break. This is not what the description said you should do. The only spaces in the output should occur after the colon (:), nowhere else.

Not a problem, but:

  • There is code repetition, i.e. your code is doing somewhat the same thing three times, once for every color. You can avoid this, by storing the counters as property values of a pain object that is keyed by the names of the colors.

Here is a correction of your code:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function report(str) {
    // Use an object to avoid code repetition in each if statement
    const counts = {
        Green: 0,
        Amber: 0,
        Red: 0,
    };

    for (const color of str.split(&quot;,&quot;)) {
        counts[color.trim()]++; // Counting is easy now...
    }
    
    return Object.entries(counts) // Get each color with its count
        .filter(([color, count]) =&gt; count) // Filter out zero-counts
        .map(([color, count]) =&gt; `${color}: ${count}`) // format as string
        .join(&quot;\n&quot;);  // join with line breaks
}

/// Some tests:
console.log(report(&quot;Green&quot;));
console.log(report(&quot;Green, Green&quot;));
console.log(report(&quot;Amber&quot;));
console.log(report(&quot;Red&quot;));
console.log(report(&quot;Red, Green, Red, Amber, Red, Green&quot;));

<!-- end snippet -->

If you want to still do this with if statements and without any of the array methods, it could look like this:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function report(str) {
    let countGreen = 0;
    let countAmber = 0;
    let countRed = 0;

    for (let color of str.split(&quot;,&quot;)) {
        color = color.trim(); // Do it only once
        if (color === &quot;Green&quot;) {
            countGreen++;
        } else if (color === &quot;Amber&quot;) {
            countAmber++;
        } else {
            countRed++;
        }
    }

    let reportCount = &quot;&quot;; // Start buiding...
    if (countGreen) {
        reportCount += &quot;Green: &quot; + countGreen + &quot;\n&quot;;
    }
    if (countAmber) {
        reportCount += &quot;Amber: &quot; + countAmber + &quot;\n&quot;;
    }
    if (countRed) {
        reportCount += &quot;Red: &quot; + countRed + &quot;\n&quot;;
    }
    return reportCount.trim(); // trim to remove final line break character
}

/// Some tests:
console.log(report(&quot;Green&quot;));
console.log(report(&quot;Green, Green&quot;));
console.log(report(&quot;Amber&quot;));
console.log(report(&quot;Red&quot;));
console.log(report(&quot;Red, Green, Red, Amber, Red, Green&quot;));

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年2月27日 05:14:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75575049.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定