ฉันมีสตริง
a.b.c.d
ฉันต้องการนับการเกิดของ '.' ในทางที่เป็นสำนวนโดยเฉพาะอย่างยิ่งหนึ่งซับ
(ก่อนหน้านี้ฉันแสดงข้อ จำกัด นี้ว่า "ไม่มีลูป" ในกรณีที่คุณสงสัยว่าทำไมทุกคนพยายามตอบโดยไม่ใช้ลูป)
ฉันมีสตริง
a.b.c.d
ฉันต้องการนับการเกิดของ '.' ในทางที่เป็นสำนวนโดยเฉพาะอย่างยิ่งหนึ่งซับ
(ก่อนหน้านี้ฉันแสดงข้อ จำกัด นี้ว่า "ไม่มีลูป" ในกรณีที่คุณสงสัยว่าทำไมทุกคนพยายามตอบโดยไม่ใช้ลูป)
คำตอบ:
'สำนวนหนึ่งซับ' ของฉันสำหรับเรื่องนี้คือ:
int count = StringUtils.countMatches("a.b.c.d", ".");
ทำไมต้องเขียนด้วยตัวคุณเองเมื่อคอมมอนส์อยู่แล้ว?
Oneliner ของ Spring Framework สำหรับสิ่งนี้คือ:
int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");
int count = CharMatcher.is('.').countIn("a.b.c.d");
... ตอบโดย dogbaneในคำถามที่ซ้ำกัน
เกี่ยวกับเรื่องนี้ ไม่ใช้ regexp ด้านล่างดังนั้นควรเร็วกว่าโซลูชันอื่น ๆ และไม่ใช้การวนซ้ำ
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 มันจะทำงานได้ แต่สำหรับ ... bc ... d หรือ ... abcd หรือ a .... b ...... c ..... d ... หรืออื่น ๆ มันจะไม่ทำงาน มันแค่จะนับ ระหว่างตัวละครเพียงครั้งเดียว
ข้อมูลเพิ่มเติมในGitHub
perfomance ทดสอบ (ใช้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()
สายนอกวงอาจทำให้ประสิทธิภาพแย่ลงได้อย่างไรดังที่ @ShuggyCoUk พูดถึง
ฉันมีความคิดคล้ายกับ 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 ("[^.]", "") ซึ่งไม่จำเป็นต้องหลบหนีเนื่องจาก [.] หมายถึงอักขระ 'dot' ไม่ใช่อักขระใด ๆ '
โซลูชัน 'สำนวนหนึ่งซับ' ของฉัน:
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));
มีห่วงอยู่ แต่มองไม่เห็น :-)
- โยนาตัน
ฉันไม่ชอบความคิดในการจัดสรรสตริงใหม่สำหรับวัตถุประสงค์นี้ และเนื่องจากสตริงนั้นมีอาร์เรย์ถ่านอยู่ด้านหลังซึ่งเก็บค่าไว้ String.charAt () จึงไม่มีค่าใช้จ่าย
for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))
หลอกลวงโดยไม่มีการจัดสรรเพิ่มเติมที่ต้องการการรวบรวมใน 1 บรรทัดหรือน้อยกว่าด้วย J2SE เท่านั้น
charAt
วนซ้ำผ่านจุดรหัส 16 บิตไม่ใช่อักขระ! A char
ใน Java ไม่ใช่อักขระ ดังนั้นคำตอบนี้บอกเป็นนัยว่าจะต้องไม่มีสัญลักษณ์ 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 ส่วนใหญ่มีการเรียกซ้ำซากในวันนี้หรือไม่ถ้าไม่คุณจะได้รับ eponymous แบบสแต็คล้นสำหรับสตริงที่มีความยาวเหมาะสม
แรงบันดาลใจจาก Jon Skeet รุ่นที่ไม่ใช่แบบวนซ้ำ จุดเริ่มต้นที่มีประโยชน์เช่นกันหากคุณต้องการใช้เฟรมเวิร์กการเข้าร่วมส้อม
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;
}
ไม่แน่ใจเกี่ยวกับประสิทธิภาพของสิ่งนี้ แต่เป็นรหัสที่สั้นที่สุดที่ฉันสามารถเขียนได้โดยไม่ต้องใส่ libs ของบุคคลที่สาม:
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 เพื่อแก้ปัญหานี้:
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 Framework คุณอาจใช้คลาส "StringUtils" วิธีนี้จะเป็น "countOccurrencesOf"
คุณสามารถใช้split()
ฟังก์ชั่นได้ในรหัสบรรทัดเดียว
int noOccurence=string.split("#",-1).length-1;
limit
ถูกตั้งค่าเป็นศูนย์ในการเรียกวิธีการแยกมากเกินไป ตัวอย่าง: "1##2#3#####".split("#")
จะให้เฉพาะอาร์เรย์ขนาด 4 ( [0:"1";1:""; 2:"2"; 3:"3"]
) แทนขนาด 9 ( [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
ในขณะที่วิธีการสามารถซ่อนมันไม่มีวิธีที่จะนับโดยไม่ต้องห่วง (หรือเรียกซ้ำ) คุณต้องการใช้อักขระ [] เพื่อเหตุผลด้านประสิทธิภาพ
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) ไม่ได้เป็นวิธีที่ดีที่สุด
ด้วยงานที่คล้ายกันมากฉัน stumbled เมื่อหัวข้อนี้ ฉันไม่เห็นข้อ จำกัด ภาษาการเขียนโปรแกรมใด ๆ และเนื่องจาก groovy ทำงานบน java vm: นี่คือวิธีที่ฉันสามารถแก้ไขปัญหาของฉันโดยใช้ Groovy
"a.b.c.".count(".")
เสร็จแล้ว
วิธีแก้ปัญหาที่ง่ายกว่าคือการแยกสตริงตามตัวละครที่คุณจับคู่ด้วย
ตัวอย่างเช่น
int getOccurences(String characters, String string) {
String[] words = string.split(characters);
return words.length - 1;
}
สิ่งนี้จะคืนค่า 4 ในกรณีของ:
getOccurences("o", "something about a quick brown fox");
บางแห่งในโค้ดมีบางสิ่งที่ต้องวนซ้ำ วิธีเดียวที่จะแก้ปัญหานี้คือการคลายลูปอย่างสมบูรณ์:
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);
}
ทำไมไม่แยกตัวละครออกแล้วรับความยาวของอาเรย์ที่เกิดขึ้น ความยาวของอาร์เรย์จะเป็นจำนวนอินสแตนซ์ + 1 ใช่ไหม
ซอร์สโค้ดต่อไปนี้จะให้หมายเลขของการเกิดขึ้นของสตริงที่กำหนดในคำที่ป้อนโดยผู้ใช้: -
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);
}
}
}
int count = (line.length() - line.replace("str", "").length())/"str".length();