2017-02-14 5 views
-2

文字/文字列のリストを指定して、リストからの出現数が特定の文字列内にあることを確認したい。JavaScriptの文字列に表示されるリスト内の項目の出現数をカウントする

const match = ['&', '|', '-', 'abc']; 
const input = 'This & That | Or | THIS - Foo abc'; 

結果は5になるはずです。

indexOfはカウンタでループすることができますが、reduceで簡単な方法があるかどうかは疑問です。

+1

あなたはどのような努力をしてきましたか? –

+0

は、今までに一文字にしかならない一致オプションですか?マッチングにとって重要なケースですか?(すなわち 'T =/= t') – haxxxton

+0

いいえ、それは1つのマッチの文字列であるかもしれません。 – chovy

答えて

2

match配列をループするのではなく、input文字列を分割してフィルタリングし、長さを取得することができます。ここで

は簡単なワンライナーです:

input.split('').filter(x => match.indexOf(x) > -1).length; 

スニペット:

const match = ['&', '|', '-']; 
 
const input = 'This & That | Or | THIS - Foo'; 
 
const count = input.split('').filter(x => match.indexOf(x) > -1).length; 
 

 
console.log(count); // 4

+0

一致文字列が 'abc'の場合、これは機能しません – chovy

1

あなたは、一致する文字を検索するために正規表現を使用することができます。

function escape(chr) { return '\\' + chr; } 

input.match(new RegExp(match.map(escape).join('|'), "g")).length 

正規表現で特別な意味を持つ|などの文字の問題を避けるためにエスケープする必要があります。

+1

' '& '、' | '、' - '、'# ']'などの値で 'match'配列が構成されていると、 '| - # 'は範囲として解釈されるので、エラー[/ [&| - #] /:文字クラス[(例)](https://jsfiddle.net/v16gjqq0/)文字クラスの内部にあります...このメソッドを使用している場合は、値をエスケープする必要があります。 '[' \\& '、' \\ | '、' \\ - '、' \\# '] '。 –

+0

@JoshCrozierありがとう、修正済み。 –

1

あなたが尋ねたので、減らし:

let count = Array.prototype.reduce.call(input, (counter, chr) => (counter + (match.indexOf(chr)!==-1 ? 1: 0)), 0) 

更新:

他の回答についてのコメントをもとに、OPはまた、個々の文字に加えて、「ABC」のような部分文字列を検索する機能をしたいと思います。ここでは、ローカルモジュールに入れることができるより洗練されたソリューションを紹介します。

一緒に機能する2つの機能があります.1つは一致する特殊文字をエスケープし、もう1つはカウントします。あなたは、配列

const match = ['&', '|', '-']; 
 
const input = 'This, & That | Or | THIS - Foo'; 
 

 
let res = match 
 
     .map(v => [...input].filter(c => c === v).length) 
 
     .reduce((a, b) => a + b) 
 

 
console.log(res);

の結果としての要素を追加するチェーン.reduce()で、.map().filter()を使用することができますし、再び減らす使用して...

 
 
// This escapes characters 
 
const escapeRegExp = (str) => (
 
    str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") 
 
) 
 
    
 
// This returns the count 
 
const countMatches = (input, match, i = true) => (
 
    match.reduce((c, pattern) => (
 
    c + input.match(new RegExp(escapeRegExp(pattern), (i ? 'ig' : 'g'))).length 
 
), 0) 
 
) 
 
    
 
// OP's test case 
 
let match = ['&', '|', '-'], 
 
    input = 'This & That | Or | THIS - Foo', 
 
    count = countMatches(input, match) 
 
console.log('Expects 4: ', count, 4 === count) 
 
    
 
    
 
// Case Sensitive Test 
 
match = ['abc'] 
 
input = 'This ABC & That abc | Or | THIS - Foo' 
 
    
 
count = countMatches(input, match, false) 
 
console.log('Expects 1: ', count, 1 === count) 
 
    
 
// Case Insensitive Test 
 
count = countMatches(input, match) 
 
console.log('Expects 2: ', count, 2 === count)

+0

なぜこれがダウンリストされたのか分かりません。 – chovy

1

0123を使用することもできます文字が結合された文字列match内にあるかどうかを調べるために、各文字を繰り返すためにループする場合は、String.prototype.contains()(サポートされている場合)または.some()をループします。

let n = 0; 
let m = match.join(""); 
for (let str of input) m.contains(str) && (n += 1); 

for (let str of input) match.some(s => s === str) && (n += 1); 
+0

なぜこれがダウン表示されますか?それは最善の答えのようです。 – chovy

関連する問題