ฉันจะนับจำนวนถ่านที่เกิดขึ้นในสตริงได้อย่างไร


547

ฉันมีสตริง

a.b.c.d

ฉันต้องการนับการเกิดของ '.' ในทางที่เป็นสำนวนโดยเฉพาะอย่างยิ่งหนึ่งซับ

(ก่อนหน้านี้ฉันแสดงข้อ จำกัด นี้ว่า "ไม่มีลูป" ในกรณีที่คุณสงสัยว่าทำไมทุกคนพยายามตอบโดยไม่ใช้ลูป)


1
การบ้าน? เพราะอย่างอื่นฉันไม่เห็นความต้องการเพื่อหลีกเลี่ยงการวนซ้ำ
PhiLho

22
ไม่รังเกียจที่จะวนซ้ำจนมองหาสำนวนหนึ่งซับ
Bart

2
ลูปถูกสร้างขึ้นมาเพื่อปัญหาเช่นนี้เขียนลูปในคลาสยูทิลิตี้ทั่วไปจากนั้นเรียกสายการบินหนึ่งซับมิ้นต์ใหม่ของคุณ
che javara

คำถามที่คล้ายกันสำหรับสตริง: stackoverflow.com/questions/767759/…
koppor

เพิ่งจะชี้ให้เห็น - ฉันซาบซึ้งในการค้นหาหนึ่งสมุทรมันสนุกและ (เป็นข้อได้เปรียบจริง) มักจะง่ายต่อการจดจำ แต่ฉันอยากจะชี้ให้เห็นว่าวิธีการที่แยกต่างหากและห่วงดีกว่าในทุก ๆ ทาง - ความสามารถในการอ่านและแม้แต่ประสิทธิภาพ โซลูชัน "Elegant" ส่วนใหญ่ด้านล่างจะทำงานได้ไม่ดีนักเนื่องจากเกี่ยวข้องกับการปฏิรูปสตริง / การคัดลอกหน่วยความจำในขณะที่ลูปที่เพิ่งสแกนสตริงและเหตุการณ์ที่เกิดขึ้นนับจะรวดเร็วและง่ายดาย โดยทั่วไปประสิทธิภาพนั้นไม่ควรเป็นปัจจัย แต่อย่ามองที่หนึ่งบรรทัดเหนือลูปและสมมติว่ามันจะทำงานได้ดีขึ้น
Bill K

คำตอบ:


722

'สำนวนหนึ่งซับ' ของฉันสำหรับเรื่องนี้คือ:

int count = StringUtils.countMatches("a.b.c.d", ".");

ทำไมต้องเขียนด้วยตัวคุณเองเมื่อคอมมอนส์อยู่แล้ว?

Oneliner ของ Spring Framework สำหรับสิ่งนี้คือ:

int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");

44
Guavaเทียบเท่า: int count = CharMatcher.is('.').countIn("a.b.c.d");... ตอบโดย dogbaneในคำถามที่ซ้ำกัน
Jonik

25
แม้ว่าฉันจะไม่ลงคะแนนนี่คือ (a) ต้องใช้ libs บุคคลที่สามและ (b) แพง
javadba

ใช้ได้กับการนำเข้ากรอบสปริงเท่านั้น
Isuru Madusanka

1
หากมีคนต้องการมัน: grepcode.com/file/repo1.maven.org/maven2/commons-lang/…
cV2

19
สิ่งที่มีราคาแพงในทุก ๆ บริษัท ที่ฉันเคยทำงานคือมีคลาส "* Utils" ที่เขียนไม่ดีและได้รับการดูแลไม่ดี ส่วนหนึ่งของงานของคุณคือการรู้ว่ามีอะไรใน Apache Commons
AbuNassar

1016

เกี่ยวกับเรื่องนี้ ไม่ใช้ regexp ด้านล่างดังนั้นควรเร็วกว่าโซลูชันอื่น ๆ และไม่ใช้การวนซ้ำ

int count = line.length() - line.replace(".", "").length();

122
วิธีที่ง่ายที่สุด ฉลาดคนหนึ่ง และใช้งานได้บน Android ที่ไม่มีคลาส StringUtils
Jose_GD

43
นี่คือคำตอบที่ดีที่สุด เหตุผลที่ดีที่สุดคือคุณไม่ต้องนำเข้าห้องสมุดอื่น
Alex Spencer

27
มีประโยชน์มาก แต่น่าเกลียดเหมือนนรก ฉันไม่แนะนำเพราะมันนำไปสู่การสับสนของรหัส
Daniel San

32
รหัสที่น่าเกลียดสามารถย่อเล็กสุดได้ด้วยการทำให้เป็นวิธีในคลาส "StringUtils" ของคุณเอง จากนั้นรหัสน่าเกลียดอยู่ในจุดเดียวและทุกที่อื่นอ่านได้อย่าง
RonR

30
วิธีห่วงคือมากเร็วกว่านี้ โดยเฉพาะอย่างยิ่งเมื่อต้องการนับถ่านแทนที่จะเป็นสตริง (เนื่องจากไม่มีวิธีการ String.replace (ถ่าน, ถ่าน)) ในสตริงตัวละคร 15 ตัวฉันได้รับความแตกต่างของ 6049 ns เทียบกับ 26,739 ns (เฉลี่ยมากกว่า 100 รัน) ตัวเลขดิบนั้นแตกต่างกันมาก แต่รับรู้ได้ดี ... มันเพิ่มขึ้น หลีกเลี่ยงการจัดสรรหน่วยความจำ - ใช้ลูป!
เบ็น

282

สรุปคำตอบอื่น ๆ และสิ่งที่ฉันรู้ทุกวิธีในการทำสิ่งนี้โดยใช้สายการบินเดียว:

   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

สตริงที่พิมพ์ออกมาไม่ตรงกับที่กล่าวมาข้างต้นและคำสั่งนั้นเร็วที่สุดก่อนซึ่งทำให้การค้นหาทำได้ยากอย่างน้อย คำตอบที่ดีอื่น ๆ !
Maarten Bodewes

กรณีที่ 2 วางมาตรฐานสำหรับ codepoints ที่ต้องการมากกว่าหนึ่งหน่วยรหัส UTF-16:"1🚲2🚲3 has 2".codePoints().filter((c) -> c == "🚲".codePointAt(0)).count()
Tom Blodget

174

ไม่ช้าก็เร็วสิ่งที่ต้องวนซ้ำ การเขียนลูป (ง่ายมาก) นั้นง่ายกว่าการใช้สิ่งที่ชอบ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;
}

จากนั้นคุณไม่จำเป็นต้องมีการวนซ้ำในรหัสหลักของคุณ - แต่การวนซ้ำจะต้องอยู่ที่ใดที่หนึ่ง


5
สำหรับ (int i = 0, L = haystack.length (); ฉัน <l; ฉัน ++) เป็นชนิดของสแต็ค
คริส

12
(ผมไม่ได้แน่ใจว่าที่ "สแต็ค" บิตของความคิดเห็นมาจากมันไม่ได้เป็นเช่น. นี้คำตอบคือหนึ่ง recursive ของฉันซึ่งเป็นที่แน่นอนที่น่ารังเกียจที่จะสแต็ค.)
จอนสกีต

2
ไม่เพียงแค่นั้น แต่นี่อาจเป็นการเพิ่มประสิทธิภาพการต่อต้านโดยไม่ดูที่ jit ทำ ถ้าคุณทำข้างบนอาร์เรย์สำหรับวนรอบตัวอย่างเช่นคุณอาจทำให้สิ่งเลวร้ายลง
ShuggyCoUk

4
@sulai: ความกังวลของคริสคือไม่มีมูลความจริง IMO ในหน้าของที่น่ารำคาญเพิ่มประสิทธิภาพ JIT มีเหตุผลใดที่ความคิดเห็นดึงดูดความสนใจของคุณในขณะนี้ในอีกสามปีต่อมา? เพียงแค่สนใจ
Jon Skeet

1
อาจ @ sulai เพิ่งเจอคำถามที่ฉันทำ (ในขณะที่สงสัยว่า Java มีวิธีการในตัวสำหรับนี้) และไม่ได้สังเกตวันที่ อย่างไรก็ตามฉันสงสัยว่าการย้ายlength()สายนอกวงอาจทำให้ประสิทธิภาพแย่ลงได้อย่างไรดังที่ @ShuggyCoUk พูดถึง
JKillian

63

ฉันมีความคิดคล้ายกับ Mladen แต่ตรงกันข้าม ...

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);

แก้ไข. ReplaceAll (".") จะแทนที่อักขระใด ๆ ไม่ใช่แค่จุด ReplaceAll ("\\.") จะใช้งานได้ ทางออกของคุณตรงไปตรงมามากขึ้น
VonC

jjnguy ได้แนะนำการเปลี่ยนทั้งหมด ("[^.]") เป็นอันดับแรกเมื่อเห็น "abcd" .split ("\\."). ความยาว -1 แต่หลังจากโดน 5 ครั้งฉันลบคำตอบของฉัน (และความคิดเห็นของเขา)
VonC

"... ตอนนี้คุณมีปัญหาสองข้อ" (ข้อผูกมัด) อย่างไรก็ตามฉันพนันได้เลยว่ามีการวนซ้ำหลายสิบครั้งในreplaceAll()และ length()ถ้าไม่สามารถมองเห็นมันก็ไม่มีอยู่ o)
Piskvor ออกจากอาคาร

2
ฉันไม่คิดว่าควรใช้ regex และสร้างสตริงใหม่สำหรับการนับ ฉันจะสร้างวิธีการคงที่วนรอบทุกตัวอักษรในสตริงเพื่อนับจำนวน
mingfai

1
@mingfai: แน่นอน แต่คำถามดั้งเดิมนั้นเกี่ยวกับการทำแบบหนึ่งบรรทัดและแม้กระทั่งโดยไม่ต้องวนซ้ำ (คุณสามารถทำแบบวนซ้ำในหนึ่งบรรทัด แต่มันจะน่าเกลียด!) ถามคำถามไม่ใช่คำตอบ ... :-)
PhiLho

37
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();

ReplaceAll (".") จะแทนที่อักขระทั้งหมด

โซลูชันของ PhiLhoใช้ ReplaceAll ("[^.]", "") ซึ่งไม่จำเป็นต้องหลบหนีเนื่องจาก [.] หมายถึงอักขระ 'dot' ไม่ใช่อักขระใด ๆ '


ฉันชอบอันนี้ แน่นอนว่ายังมีการวนซ้ำเหมือนเดิม
เทพพอล

NB ที่คุณต้องหารจำนวนนี้ถ้าคุณต้องการค้นหาสตริงความยาว> 1
rogerdpack

30

โซลูชัน 'สำนวนหนึ่งซับ' ของฉัน:

int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();

ไม่มีความคิดว่าเหตุใดจึงยอมรับโซลูชันที่ใช้ StringUtils


4
มีวิธีแก้ไขแบบเก่าที่คล้ายกับโซลูชันนี้ในโพสต์นี้
JCalcines

7
เพราะวิธีนี้ไม่มีประสิทธิภาพจริงๆ
András

สิ่งนี้สร้างสตริงพิเศษเพียงเพื่อสร้างการนับ ไม่มีความคิดว่าทำไมทุกคนจะชอบสิ่งนี้มากกว่า StringUtils หาก StringUtils เป็นตัวเลือก ถ้ามันไม่ใช่ตัวเลือกพวกเขาก็ควรสร้าง simple สำหรับ loop ในคลาสยูทิลิตี้
บดขยี้


24

ตัวอย่างที่สั้นกว่าคือ

String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;

3
อันนี้ดูเหมือนว่าจะมีค่าใช้จ่ายที่ค่อนข้างใหญ่ได้รับการเตือนว่ามันอาจสร้างสตริงขนาดเล็กจำนวนมาก ปกติแล้วมันจะไม่สำคัญอะไร แต่ควรใช้ด้วยความระมัดระวัง
Maarten Bodewes

19

นี่คือวิธีการแก้ปัญหาโดยไม่ต้องห่วง:

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));

มีห่วงอยู่ แต่มองไม่เห็น :-)

- โยนาตัน


2
นอกเสียจากว่าสตริงของคุณจะยาวคุณจะได้รับ OutOfMemoryError
Spencer Kormos

ปัญหาดูเหมือนจะเป็นการพอที่จะทำการบ้านและถ้าเป็นเช่นนั้นการสอบถามซ้ำนี้อาจเป็นคำตอบที่คุณถูกขอให้ค้นหา
erickson

ที่ใช้ indexOf ซึ่งจะวนซ้ำ ... แต่เป็นความคิดที่ดี โพสต์วิธีการแก้ปัญหาอย่างแท้จริง "เพียงแค่เรียกซ้ำ" ในนาที ...
จอนสกีต

หากมีเหตุการณ์เพิ่มเติมที่สแต็กสล็อตที่มีอยู่ของคุณคุณจะมีข้อยกเว้นสแต็กล้น)
Luca C.

15

ฉันไม่ชอบความคิดในการจัดสรรสตริงใหม่สำหรับวัตถุประสงค์นี้ และเนื่องจากสตริงนั้นมีอาร์เรย์ถ่านอยู่ด้านหลังซึ่งเก็บค่าไว้ String.charAt () จึงไม่มีค่าใช้จ่าย

for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))

หลอกลวงโดยไม่มีการจัดสรรเพิ่มเติมที่ต้องการการรวบรวมใน 1 บรรทัดหรือน้อยกว่าด้วย J2SE เท่านั้น


ให้ความรักกับคนนี้เพราะมันเป็นสิ่งเดียวที่ทำผ่านสายเดียว ฉันสนใจเกี่ยวกับการแสดง
javadba

1
charAtวนซ้ำผ่านจุดรหัส 16 บิตไม่ใช่อักขระ! A charใน Java ไม่ใช่อักขระ ดังนั้นคำตอบนี้บอกเป็นนัยว่าจะต้องไม่มีสัญลักษณ์ Unicode ที่มีตัวแทนdelimสำรองสูงเท่ากับจุดรหัสของ ฉันไม่แน่ใจว่าถูกต้องสำหรับจุดหรือไม่ แต่โดยทั่วไปแล้วอาจไม่ถูกต้อง
ceving

14

โอเคได้รับแรงบันดาลใจจากวิธีแก้ปัญหาของ 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 แบบสแต็คล้นสำหรับสตริงที่มีความยาวเหมาะสม


ไม่การเรียกซ้ำหางอาจเป็นใน Java 7 แต่ยังไม่แพร่หลาย การเรียกซ้ำหางโดยตรงแบบง่ายนี้สามารถแปลเป็นลูปในเวลารวบรวม แต่สิ่ง Java 7 นั้นมีอยู่แล้วใน JVM เพื่อจัดการกับการโยงผ่านวิธีการต่าง ๆ
erickson

3
คุณมีแนวโน้มที่จะได้รับการเรียกซ้ำอีกครั้งหากวิธีการของคุณส่งคืนการเรียกร้องให้ตัวเอง (รวมถึงพารามิเตอร์ทั้งหมดที่กำลังทำงานอยู่) แทนที่จะส่งกลับผลลัพธ์ของการดำเนินการเพิ่มเติม
สตีเฟ่น Denne

12

แรงบันดาลใจจาก 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;
}

11

ไม่แน่ใจเกี่ยวกับประสิทธิภาพของสิ่งนี้ แต่เป็นรหัสที่สั้นที่สุดที่ฉันสามารถเขียนได้โดยไม่ต้องใส่ libs ของบุคคลที่สาม:

public static int numberOf(String target, String content)
{
    return (content.split(target).length - 1);
}

4
ยังนับปรากฏในตอนท้ายของสตริงที่คุณจะต้องแยกการโทรที่มีการโต้แย้งขีด จำกัด return (content.split(target, -1).length - 1);ในเชิงลบเช่นนี้: โดยค่าเริ่มต้นที่เกิดขึ้นในตอนท้ายของสตริงจะถูกละเว้นในอาร์เรย์ที่เกิดจากการแยก () ดูDoku
vlz

10

กับ คุณสามารถใช้สตรีมเพื่อทำสิ่งนี้ เห็นได้ชัดว่ามีการทำซ้ำเบื้องหลัง แต่คุณไม่จำเป็นต้องเขียนอย่างชัดเจน!

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 ใด ๆ (รวมถึงผู้ที่ต้องการคู่ตัวแทน)
ลุค Usherwood

10

เป็นไปได้ที่จะใช้การลดใน Java 8 เพื่อแก้ปัญหานี้:

int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0));
System.out.println(res);

เอาท์พุท:

3

8

ตัวอย่างที่สมบูรณ์:

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

รหัสผิดมันไม่ทำงานเมื่อฉันลอง int เกิดขึ้น = CharacterCounter.countOccurrences ("1", "101"); System.out.println (เกิดขึ้น); // 1
jayesh

ฉันส่งรหัสแก้ไขซึ่งใช้งานได้กับตรรกะเดียวกัน
MaanooAk

8

วิธีที่ง่ายที่สุดในการรับคำตอบมีดังนี้:

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));
}

2
ตัวอย่างข้อมูลนี้ไม่ได้ส่งคืนเงินที่ถูกต้องของจุดสำหรับการป้อนข้อมูลได้รับ "เอบีซี"
dekaru

@dekaru คุณช่วยวางสติงของคุณในความคิดเห็นเพื่อที่เราจะได้ดู
Amar Magar

5

ในกรณีที่คุณใช้ Spring Framework คุณอาจใช้คลาส "StringUtils" วิธีนี้จะเป็น "countOccurrencesOf"


5

คุณสามารถใช้split()ฟังก์ชั่นได้ในรหัสบรรทัดเดียว

int noOccurence=string.split("#",-1).length-1;

แยกได้สร้างอาร์เรย์ของสตริงซึ่งใช้เวลามาก
Palec

คุณสิทธิว่าเป็นความจริงความกังวล อีกวิธีหนึ่งคือหลีกเลี่ยงการนำ lib บุคคลที่สามในโครงการของคุณ (ถ้ายังไม่ได้ทำ) ขึ้นอยู่กับสิ่งที่คุณต้องการจะทำและสิ่งที่คาดหวังประสิทธิภาพ
Benj

3
วิธีการแก้ปัญหานี้จะไม่รวมการเข้าชมว่างเปล่าต่อท้ายเพราะอาร์กิวเมนต์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:""])
klaar

4
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;
}

4
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

3

ในขณะที่วิธีการสามารถซ่อนมันไม่มีวิธีที่จะนับโดยไม่ต้องห่วง (หรือเรียกซ้ำ) คุณต้องการใช้อักขระ [] เพื่อเหตุผลด้านประสิทธิภาพ

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) ไม่ได้เป็นวิธีที่ดีที่สุด


ฉันคิดว่านี่เป็นทางออกที่หรูหราที่สุด เหตุใดคุณจึงใช้ toCharArray และไม่ใช่ charAt โดยตรง
Panayotis

วนอย่างน้อยก็จะช้าลง อาจขึ้นอยู่กับแพลตฟอร์มด้วย วิธีเดียวที่จะค้นหาความจริงก็คือการวัดความแตกต่าง
tcurdt

3

ด้วยงานที่คล้ายกันมากฉัน stumbled เมื่อหัวข้อนี้ ฉันไม่เห็นข้อ จำกัด ภาษาการเขียนโปรแกรมใด ๆ และเนื่องจาก groovy ทำงานบน java vm: นี่คือวิธีที่ฉันสามารถแก้ไขปัญหาของฉันโดยใช้ Groovy

"a.b.c.".count(".")

เสร็จแล้ว


3

วิธีแก้ปัญหาที่ง่ายกว่าคือการแยกสตริงตามตัวละครที่คุณจับคู่ด้วย

ตัวอย่างเช่น

int getOccurences(String characters, String string) { String[] words = string.split(characters); return words.length - 1; }

สิ่งนี้จะคืนค่า 4 ในกรณีของ: getOccurences("o", "something about a quick brown fox");


ปัญหาตรงนี้คือต้องมีการจัดสรรอาเรย์ซึ่งช้ามาก
Palec

2

บางแห่งในโค้ดมีบางสิ่งที่ต้องวนซ้ำ วิธีเดียวที่จะแก้ปัญหานี้คือการคลายลูปอย่างสมบูรณ์:

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

2

นี่คือวิธีการแก้ปัญหาการเรียกซ้ำรูปแบบที่แตกต่างกันเล็กน้อย:

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);
}

2

ทำไมไม่แยกตัวละครออกแล้วรับความยาวของอาเรย์ที่เกิดขึ้น ความยาวของอาร์เรย์จะเป็นจำนวนอินสแตนซ์ + 1 ใช่ไหม


2

ซอร์สโค้ดต่อไปนี้จะให้หมายเลขของการเกิดขึ้นของสตริงที่กำหนดในคำที่ป้อนโดยผู้ใช้: -

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);
        }

    }
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.