Skip to content

Instantly share code, notes, and snippets.

@jinmayamashita
Last active February 27, 2020 23:45
Show Gist options
  • Save jinmayamashita/6bd4cc21ada3f502197ada9d25e6f653 to your computer and use it in GitHub Desktop.
Save jinmayamashita/6bd4cc21ada3f502197ada9d25e6f653 to your computer and use it in GitHub Desktop.
word_count
const englishString =
"The administration will encourage federal data and universities to share data that can drive the administration of automated systems data";
const toSplitBySeparator = (splitTarget, separator) =>
splitTarget.toLowerCase().split(separator);
const countWord = stringArray => {
let word = "";
let count = 0;
const processingEndWords = [];
for (let i = 0; i < stringArray.length; i++) {
word = stringArray[i];
count = 0;
for (let j = 0; j < stringArray.length; j++) {
if (word === stringArray[j]) {
count++;
}
}
let find = processingEndWords.find(item => word === item);
if (!find) {
processingEndWords.push(word);
console.log(`${word}: ${count}`);
}
}
};
countWord(toSplitBySeparator(englishString, " "));
const str =
"Until last week, Ms. Morales kept the episode to herself. But after another But woman came forward to file. Her a criminal complaint against the former president alleging a sexual assault, Ms. Morales summoned the courage to add her voice.";
const filterToPureWords = englishSentence =>
englishSentence
.toLowerCase()
.replace(/\W/g, " ")
.split(" ")
.filter(word => /\w/.test(word));
const saveCountWordToMap = (stringArray, map) => {
for (let word of stringArray) {
let count = 0;
stringArray.find(targetWord => {
if (word === targetWord) {
count++;
}
map.set(word, count);
});
}
return map;
};
const wordCountMap = new Map();
const result = saveCountWordToMap(filterToPureWords(str), wordCountMap);
console.log(result);
const str =
"Until last week, Ms. Morales kept the episode to herself. But after another But woman came forward to file. Her a criminal complaint against the former president alleging a sexual assault, Ms. Morales summoned the courage to add her voice.";
const filterToPureWords = englishSentence =>
englishSentence
.toLowerCase()
.replace(/\W/g, " ")
.split(" ")
.filter(word => /\w/.test(word));
const countWord = (stringArray, word) =>
stringArray.filter(item => item === word).length;
const saveToMap = (stringArray, map, countFunc) => {
for (let word of stringArray) {
map.set(word, countFunc(stringArray, word));
}
return map;
};
const result = saveToMap(filterToPureWords(str), new Map(), countWord);
console.log(result);
const str =
"independent independent independent similar similar similar similar similar similar successful successful enormous busy basic massive massive massive massive massive sings sings sings sings";
const filterToPureWords = englishSentence =>
englishSentence
.toLowerCase()
.replace(/\W/g, " ")
.split(" ")
.filter(word => /\w/.test(word));
const countWord = (stringArray, word) =>
stringArray.filter(item => item === word).length;
const sortCount = ({ sortTarget, desc }) => {
if (desc) {
return sortTarget.sort(
(compare1, compare2) =>
Object.values(compare2)[0] - Object.values(compare1)[0]
);
}
return sortTarget.sort(
(compare1, compare2) =>
Object.values(compare1)[0] - Object.values(compare2)[0]
);
};
const saveToArray = (stringArray, countFunc) => {
const arrayWithWordCounts = []
for (let word of stringArray) {
/**
* TODO: how get object key in array ?
*/
arrayWithWordCounts.push({ [word]: countFunc(stringArray, word) });
}
return arrayWithWordCounts;
};
const result = saveToArray(
filterToPureWords(str),
countWord
);
sortCount({ sortTarget: result, desc: true });
console.log(result.slice(0, 5));
const str =
"Until last week, Ms. Morales kept the episode to herself. But after another But woman came forward to file. Her a criminal complaint against the former president alleging a sexual assault, Ms. Morales summoned the courage to add her voice.";
const filterToPureCharacter = englishSentence =>
Array.from(englishSentence)
const saveCountCharacterToMap = (stringArray, map) => {
for (let c of stringArray) {
let count = 0;
stringArray.find(targetCharacter => {
if (c === targetCharacter) {
count++;
map.set(targetCharacter, count);
}
});
}
return map;
};
const characterCountMap = new Map();
const result = saveCountCharacterToMap(filterToPureCharacter(str), characterCountMap);
console.log(result);
@jinmayamashita
Copy link
Author

jinmayamashita commented Feb 12, 2019

  • 文字列を英単語をカウントできるようにする

    • 文字列の空欄を基準に英単語を区切る
      (今回は大文字、小文字区分無しで区切る)
    • 文字列を特定条件で区切ってくれるJavaScriptのAPIを調べる
    • 区切った文字列を配列に入れて置く、それで配列を回しながらカウント処理を行いたい
  • カウント処理

    • 区切られた文字配列のアイテムに対して繰り返してカウント処理を行う
    • 英単語比較用の変数を定義、配列のアイテムと同じ英単語かを比較する
    • 英単語カウント用の変数を定義、カウントした数字を入れとく
    • 英単語一個に対して配列を1回度にカウントを数える
    • 英単語一個に対して配列を1回した後に、英単語比較用の変数と英単語カウントをリセットする
  • 英単語をカウントした結果を出力、または保存する

    • 区切った文字列を回しながら word(string) : count(number) の形で画面に出す
      • 以前カウントした英単語を重複表示していることを分かった、既にカウントした単語を飛ばすようにロジックを入れた
      • カウントした結果が小文字で出力される
  • inputの文字列を違う文字列に変えてカウントロジックが動作するか確認

@kogai
Copy link

kogai commented Feb 12, 2019

このコードに至った手順を書いたら、以下の応用問題を解いてみて下さい
(ひとつずつでOKです)

  • 改行コード、絵文字、数値が含まれていても意図したとおりに動作することを確認して下さい
  • カウントした単語を出現回数順に上位5個取得して下さい
  • 単語ではなく、文字の出現回数をカウントして下さい

@jinmayamashita
Copy link
Author

jinmayamashita commented Feb 12, 2019

@jinmayamashita
Copy link
Author

仕様は、

英語で書かれた文字列中に含まれる英単語の個数を単語ごとにカウントする

それに対して最初、分かったなかったことは、

  • 文字列をどういう基準で区切ったらいいか(仕様には書いていない)
    • 空欄で区切ったらいいかと思ったが、英単語に,.など含まれている場合がある -> MDNでRegular Expressionsを調べた
  • 大文字、小文字を同じ英単語としてカウントするのか(仕様には書いていない)-> 大文字、小文字を同じ英単語として考えた
  • カウント自体はどうやって出来るのか分かったいない -> 繰り返しの中に変数があればカウント出来ると思った。
  • カウント結果についてどうすればいいのかも分かったいない(仕様には書いていない)-> 何かのデータに入れときたかった。-> MDNでMapを調べた。

@jinmayamashita
Copy link
Author

  • 改行コード、絵文字、数値が含まれていても意図したとおりに動作することを確認して下さい

改行コードが含まれていても意図したとおりに動作していた。
絵文字が含まれている場合、絵文字がカウントされない。

  • 数値が含まれていることは、
const string = "123 something word 123"

に対して、下記のように

{ 
  '123' => 2,
  'something' => 1,
  'word' => 1
}

結果を返すので意図したとおりに動作するという認識でしょうか @kogai 🙏

@jinmayamashita
Copy link
Author

jinmayamashita commented Feb 12, 2019

  • 改行コード、絵文字、数値が含まれていても意図したとおりに動作することを確認して下さい

↑はまず、パスすることで、

  • カウントした単語を出現回数順に上位5個取得して下さい

明日、↑の問題から推論、質問する

@jinmayamashita
Copy link
Author

  • カウントした単語を出現回数順に上位5個取得して下さい

について質問があります 🙏 @kogai

  1. 入力(input)と出力(output)は下記の形という認識でしょうか。

input:

const string = "a a a a b b c c c d e"

output:

["a", "c", "b", "d", "e"]
  1. 出現回数順が同じ回数の場合はどうしましょうか。(上記の場合、dが1回、 eが1回)

@jinmayamashita
Copy link
Author

jinmayamashita commented Feb 13, 2019

  • カウントした単語を出現回数順に上位5個取得して下さい

について

  • 分かること
    • 単語はカウントしされていること
    • 出現回数が多い順上位5個を取得すること
      • 多い順では無かったということ、多い順か少ない順かは決まっていないという話だった。
  • 分かっていないこと
    • 上位5個取得というのはどういうデータ構造で取得するのか
      • データ構造はなんでもいい。ただ、{word:count}になって入れば良いという話
    • 同じ回数の場合はどういう順番で判断するのか
        * 同じ回数の場合は上位4個まで取得する
    • 現在のデータ構造はMapになっている。Mapの中身をカウント順に配置すること
      • これは仕様に関する質問では無かった。

@jinmayamashita
Copy link
Author

jinmayamashita commented Feb 13, 2019

https://gist.github.com/jinmayamashita/6bd4cc21ada3f502197ada9d25e6f653#file-word_count_v4-js

アプローチしたこと

  • カウントした単語を出現回数順する必要があった -> データ構造をMapから配列だと解決出来ると思った。配列に変更し、sort関数を追加した。

    • sortは多い順か少ない順か分かっていない -> parameterにdescというoptionがあると解決出来ると思った
    • 配列には { word: count }の形で保存した
  • 上位5個まで取得する必要があった -> 配列には.slice()があるので調査して追加した。

  • 解答できなかったこと

@jinmayamashita
Copy link
Author

jinmayamashita commented Feb 13, 2019

単語ではなく、文字の出現回数をカウントして下さい

  • 今はfilterToPureWordsという関数で単語を区切った配列を返している

  • filterToPureWords関数の中を単語基準で区切らない。文字基準で区切るように変更する

    • 文字列を区切る基準は正規表現で判定している
    • 正規表現で単語ではなく、文字を判定するpatternがあると思う。-> 調査する
    • または、文字列を文字別でArrayのアイテムにするAPIがあると思う -> 正規表現のpatternが見つからなかったら、調査する
    • .replace()で文字ではない ., ,, を削除する
    • .split()の中に正規表現の文字を判定するpatternで区切って配列に入れる
  • 単語ではなく、文字を区切るようになる。そのため不要なJavaScript API関数を削除する

    • .toLowerCase(), .filter()は不要ではないか?-> 試してみる
  • filterToPureWordsからfilterToPureCharacterに関数名を変える

  • 文字の出現回数のカウントを確認しやすくするため、変数englishStringの中身を変える

  • filterToPureCharacterenglishString以外の部分は変更無し


  • これは分かったない。調べる

    • 正規表現で単語ではなく、文字を判定するpatternがあるか調査する
    • 文字列を文字別でArrayのアイテムにするAPIを調査する
  • これは分かったない。聞いてみる

    • 大文字と小文字は同じ文字として判断するのか、それとも違う文字として判断するのか?
    • word_count_v4.jsは論理的ではない実装をしている。文字の出現回数をカウントするのを word_count_v2.jsで実装してもいいか相談してみる @kogai

@jinmayamashita
Copy link
Author

jinmayamashita commented Feb 13, 2019

単語ではなく、文字の出現回数をカウントして下さい

  • 今はfilterToPureWordsという関数で単語を区切った配列を返している

  • filterToPureWords関数の中を単語基準ではなく文字基準で区切るようにする

    • 文字列を区切る基準は正規表現で判定している
    • 正規表現で文字を判定するpatternを調査する
      • MDN Documentでは文字(アルファベット)を判定するpatternが分からない -> 一旦止める
    • または、文字列を文字別でArrayに変換出来るかAPIを調査する
      • Array.from(文字列)というAPIが文字列をアルファベット基準でArrayにしてくれることを分かった。
    • .split()の中に正規表現(文字列を区切る基準は正規表現)を入れれるのか調査する
      • Array.from(文字列)を使うことで.split()は不要になった
  • 単語ではなく、文字を区切るようになる。そのため不要なJavaScript API関数を削除する

    • .toLowerCase(), .filter()は不要ではないか?-> 試してみる
      • .toLowerCase()はまず、仕様を確認が必要、 .filter()はここにかく必要はない
  • filterToPureWordsからfilterToPureCharacterに関数名を変える


小飼さんと相談後に実装に反映したこと

  • 大文字と小文字は区分する
  • 単語ではなく、文字の出現回数ので、既存のsaveCountWordToMapwordCountMapなどの
    変数、関数名をsaveCountCharacterToMapcharacterCountMapに変更

結果:
https://gist.github.com/jinmayamashita/6bd4cc21ada3f502197ada9d25e6f653#file-word_count_v5-js
https://repl.it/@jinma/TrustingCalculatingViruses

@jinmayamashita
Copy link
Author

jinmayamashita commented Feb 13, 2019

saveCountCharacterToMap関数の中のロジック中、
map.set()するタイミングが間違えていた!下記のように修正しました。:pray: @kogai

https://gist.github.com/jinmayamashita/6bd4cc21ada3f502197ada9d25e6f653#file-word_count_v5-js-L13

repl:
https://repl.it/@jinma/TrustingCalculatingViruses

@jinmayamashita
Copy link
Author

jinmayamashita commented Feb 13, 2019

  • .replace()で文字ではない ., ,, を削除する

の話は仕様には無かった。。

仕様は., ,, を一つの文字としてカウントして欲しいという内容だったので、

., ,, をフィルターする必要はなくなった。
.filter(character => /\w/.test(character)); のところを削除した。

diff:
https://gist.github.com/jinmayamashita/6bd4cc21ada3f502197ada9d25e6f653/revisions#diff-8ff03d2e1306d7e1d86e5f2d06b0474b

repl:
https://repl.it/@jinma/TrustingCalculatingViruses

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment