私はひもを持っています
a.b.c.d
「。」の出現回数を数えたい 慣用的な方法で、できればワンライナー。
(以前は、誰もがループを使用せずに答えようとしているのか疑問に思っている場合に備えて、この制約を「ループなし」と表現していました)。
私はひもを持っています
a.b.c.d
「。」の出現回数を数えたい 慣用的な方法で、できればワンライナー。
(以前は、誰もがループを使用せずに答えようとしているのか疑問に思っている場合に備えて、この制約を「ループなし」と表現していました)。
回答:
これに対する私の「慣用的なワンライナー」は次のとおりです。
int count = StringUtils.countMatches("a.b.c.d", ".");
すでにcommons langになっているのに、なぜ自分で書くのですか?
これに対するSpring Frameworkのワンライナーは次のとおりです。
int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");
これはどう。それは下で正規表現を使用しないので、他のソリューションのいくつかよりも速く、ループを使用しません。
int count = line.length() - line.replace(".", "").length();
他の回答と、ワンライナーを使用してこれを行うすべての方法を私が知っていることを要約します。
String testString = "a.b.c.d";
1)Apache Commonsの使用
int apache = StringUtils.countMatches(testString, ".");
System.out.println("apache = " + apache);
2)Spring Frameworkの使用
int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, ".");
System.out.println("spring = " + spring);
3)置換の使用
int replace = testString.length() - testString.replace(".", "").length();
System.out.println("replace = " + replace);
4)replaceAllを使用する(ケース1)
int replaceAll = testString.replaceAll("[^.]", "").length();
System.out.println("replaceAll = " + replaceAll);
5)replaceAllを使用する(ケース2)
int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length();
System.out.println("replaceAll (second case) = " + replaceAllCase2);
6)分割を使用する
int split = testString.split("\\.",-1).length-1;
System.out.println("split = " + split);
7)Java8の使用(ケース1)
long java8 = testString.chars().filter(ch -> ch =='.').count();
System.out.println("java8 = " + java8);
8)Java8(ケース2 )を使用すると、ケース1よりもユニコードの方が良い場合があります
long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count();
System.out.println("java8 (second case) = " + java8Case2);
9)StringTokenizerの使用
int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1;
System.out.println("stringTokenizer = " + stringTokenizer);
コメントから:StringTokenizerには注意してください。abcdの場合は機能しますが、a ... bc ... dまたは... abcdまたはa .... b ...... c ..... dの場合は注意してください。 ...などは動作しません。それだけでカウントされます。キャラクター間で一度だけ
githubの詳細
パフォーマンステスト(JMHを使用、モード= AverageTime、0.010
より良いスコア0.351
):
Benchmark Mode Cnt Score Error Units
1. countMatches avgt 5 0.010 ± 0.001 us/op
2. countOccurrencesOf avgt 5 0.010 ± 0.001 us/op
3. stringTokenizer avgt 5 0.028 ± 0.002 us/op
4. java8_1 avgt 5 0.077 ± 0.005 us/op
5. java8_2 avgt 5 0.078 ± 0.003 us/op
6. split avgt 5 0.137 ± 0.009 us/op
7. replaceAll_2 avgt 5 0.302 ± 0.047 us/op
8. replace avgt 5 0.303 ± 0.034 us/op
9. replaceAll_1 avgt 5 0.351 ± 0.045 us/op
"1🚲2🚲3 has 2".codePoints().filter((c) -> c == "🚲".codePointAt(0)).count()
遅かれ早かれ、何かがループする必要があります。(非常に単純な)ループを記述するsplit
方が、必要以上に強力なものを使用するよりもはるかに簡単です。
必ず別の方法でループをカプセル化してください。
public static int countOccurrences(String haystack, char needle)
{
int count = 0;
for (int i=0; i < haystack.length(); i++)
{
if (haystack.charAt(i) == needle)
{
count++;
}
}
return count;
}
そうすれば、メインコードにループを含める必要はありませんが、ループはどこかにある必要があります。
length()
呼び出しをループの外に移動するとパフォーマンスが低下する可能性があることに興味があります。
Mladenに似たアイデアがありましたが、その逆です...
String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);
replaceAll()
てlength()
いるループが数十あると思います。まあ、それが見えなければ、それは存在しません; o)
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();
ReplaceAll( "。")はすべての文字を置き換えます。
PhiLhoのソリューションでは、ReplaceAll( "[^。]"、 "")を使用します。これは、[。]が「任意の文字」ではなく「ドット」を表すため、エスケープする必要はありません。
私の「慣用的なワンライナー」ソリューション:
int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();
StringUtilsを使用するソリューションが受け入れられる理由がわかりません。
String s = "a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();
短い例は
String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;
ここにループのない解決策があります:
public static int countOccurrences(String haystack, char needle, int i){
return ((i=haystack.indexOf(needle, i)) == -1)?0:1+countOccurrences(haystack, needle, i+1);}
System.out.println("num of dots is "+countOccurrences("a.b.c.d",'.',0));
まあ、ループがありますが、それは見えません :-)
-よなたん
この目的のために新しい文字列を割り当てるという考えは好きではありません。また、文字列はその値を格納する後ろにすでにchar配列を持っているため、String.charAt()は事実上無料です。
for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))
J2SEのみで、収集を必要とする追加の割り当てなしで、1行以下でトリックを実行します。
charAt
文字ではなく16ビットのコードポイントを反復処理します。char
JavaのA は文字ではありません。したがって、この答えは、サロゲートがのコードポイントに等しいUnicodeシンボルがあってはならないことを意味しdelim
ます。ドットに対して正しいかどうかはわかりませんが、一般的には正しくない可能性があります。
さて、Yonatanのソリューションに触発され、ここにある一つだ純粋に再帰-使用のみのライブラリの方法があるlength()
とcharAt()
、どちらも任意のループ操作を行います。
public static int countOccurrences(String haystack, char needle)
{
return countOccurrences(haystack, needle, 0);
}
private static int countOccurrences(String haystack, char needle, int index)
{
if (index >= haystack.length())
{
return 0;
}
int contribution = haystack.charAt(index) == needle ? 1 : 0;
return contribution + countOccurrences(haystack, needle, index+1);
}
再帰がループとしてカウントされるかどうかは、使用する正確な定義に依存しますが、それはおそらくあなたが得るものと同じくらい近いです。
最近、ほとんどのJVMが末尾再帰を実行するかどうかはわかりませんが、そうでない場合は、当然のことながら、適切に長い文字列に対して、代名詞のスタックオーバーフローが発生します。
スタックを爆破しない非ループバージョンのJon Skeetに触発されました。また、fork-joinフレームワークを使用する場合の出発点としても役立ちます。
public static int countOccurrences(CharSequeunce haystack, char needle) {
return countOccurrences(haystack, needle, 0, haystack.length);
}
// Alternatively String.substring/subsequence use to be relatively efficient
// on most Java library implementations, but isn't any more [2013].
private static int countOccurrences(
CharSequence haystack, char needle, int start, int end
) {
if (start == end) {
return 0;
} else if (start+1 == end) {
return haystack.charAt(start) == needle ? 1 : 0;
} else {
int mid = (end+start)>>>1; // Watch for integer overflow...
return
countOccurrences(haystack, needle, start, mid) +
countOccurrences(haystack, needle, mid, end);
}
}
(免責事項:テストされていない、コンパイルされていない、賢明ではない。)
おそらくそれを書くための最良の(シングルスレッド、サロゲートペアのサポートなし)方法:
public static int countOccurrences(String haystack, char needle) {
int count = 0;
for (char c : haystack.toCharArray()) {
if (c == needle) {
++count;
}
}
return count;
}
これの効率についてはわかりませんが、サードパーティのライブラリを導入せずに書ける最短のコードです。
public static int numberOf(String target, String content)
{
return (content.split(target).length - 1);
}
と java-8ストリームを使用してこれを実現することもできます。明らかに裏でイテレーションがありますが、明示的に記述する必要はありません。
public static long countOccurences(String s, char c){
return s.chars().filter(ch -> ch == c).count();
}
countOccurences("a.b.c.d", '.'); //3
countOccurences("hello world", 'l'); //3
.codePoints()
代わりに.chars()
を使用すると、任意のUnicode値(サロゲートペアが必要なものを含む)がサポートされます
この問題を解決するためにJava 8でreduceを使用することもできます。
int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0));
System.out.println(res);
出力:
3
完全なサンプル:
public class CharacterCounter
{
public static int countOccurrences(String find, String string)
{
int count = 0;
int indexOf = 0;
while (indexOf > -1)
{
indexOf = string.indexOf(find, indexOf + 1);
if (indexOf > -1)
count++;
}
return count;
}
}
コール:
int occurrences = CharacterCounter.countOccurrences("l", "Hello World.");
System.out.println(occurrences); // 3
答えを得る最も簡単な方法は次のとおりです。
public static void main(String[] args) {
String string = "a.b.c.d";
String []splitArray = string.split("\\.",-1);
System.out.println("No of . chars is : " + (splitArray.length-1));
}
Springフレームワークを使用している場合は、「StringUtils」クラスも使用できます。メソッドは「countOccurrencesOf」になります。
split()
関数は1行のコードで使用できます
int noOccurence=string.split("#",-1).length-1;
limit
オーバーロードされた分割メソッド呼び出しで引数がゼロに設定されているため、このソリューションには後続の空のヒットは含まれません。例:サイズ9()ではなく"1##2#3#####".split("#")
、サイズ4([0:"1";1:""; 2:"2"; 3:"3"]
)の配列のみを生成し[0:"1"; 1:""; 2:"2"; 3:"3"; 4:""; 5:""; 6:""; 7:""; 8:""]
ます。
public static int countOccurrences(String container, String content){
int lastIndex, currIndex = 0, occurrences = 0;
while(true) {
lastIndex = container.indexOf(content, currIndex);
if(lastIndex == -1) {
break;
}
currIndex = lastIndex + content.length();
occurrences++;
}
return occurrences;
}
import java.util.Scanner;
class apples {
public static void main(String args[]) {
Scanner bucky = new Scanner(System.in);
String hello = bucky.nextLine();
int charCount = hello.length() - hello.replaceAll("e", "").length();
System.out.println(charCount);
}
}// COUNTS NUMBER OF "e" CHAR´s within any string input
メソッドはそれを隠すことができますが、ループ(または再帰)なしでカウントする方法はありません。ただし、パフォーマンス上の理由からchar []を使用したい場合。
public static int count( final String s, final char c ) {
final char[] chars = s.toCharArray();
int count = 0;
for(int i=0; i<chars.length; i++) {
if (chars[i] == c) {
count++;
}
}
return count;
}
replaceAll(つまりRE)を使用するのは、最良の方法とは思えません。
まあ、非常によく似たタスクで、このスレッドに出くわしました。プログラミング言語の制限はありませんでした。groovyはjava vmで実行されているため、次のようにしてGroovyを使用して問題を解決できました。
"a.b.c.".count(".")
完了しました。
コードのどこかで、何かがループしなければなりません。これを回避する唯一の方法は、ループを完全に展開することです。
int numDots = 0;
if (s.charAt(0) == '.') {
numDots++;
}
if (s.charAt(1) == '.') {
numDots++;
}
if (s.charAt(2) == '.') {
numDots++;
}
...など、ただし、ソースエディターで手動でループを実行するのは、それを実行するコンピューターではありません。擬似コードを参照してください:
create a project
position = 0
while (not end of string) {
write check for character at position "position" (see above)
}
write code to output variable "numDots"
compile program
hand in homework
do not think of the loop that your "if"s may have been optimized and compiled to
これは少し異なるスタイルの再帰ソリューションです:
public static int countOccurrences(String haystack, char needle)
{
return countOccurrences(haystack, needle, 0);
}
private static int countOccurrences(String haystack, char needle, int accumulator)
{
if (haystack.length() == 0) return accumulator;
return countOccurrences(haystack.substring(1), needle, haystack.charAt(0) == needle ? accumulator + 1 : accumulator);
}
次のソースコードは、ユーザーが入力した単語内の特定の文字列の出現回数を示します。
import java.util.Scanner;
public class CountingOccurences {
public static void main(String[] args) {
Scanner inp= new Scanner(System.in);
String str;
char ch;
int count=0;
System.out.println("Enter the string:");
str=inp.nextLine();
while(str.length()>0)
{
ch=str.charAt(0);
int i=0;
while(str.charAt(i)==ch)
{
count =count+i;
i++;
}
str.substring(count);
System.out.println(ch);
System.out.println(count);
}
}
}