ดัชนีของอักขระทั้งหมดในสตริง


105

รหัสต่อไปนี้จะพิมพ์ 2

String word = "bannanas";
String guess = "n";
int index;
System.out.println( 
    index = word.indexOf(guess)
);

ฉันต้องการทราบวิธีรับดัชนีทั้งหมดของ "n" ("guess") ในสตริง "bannanas"

ผลลัพธ์ที่คาดหวังคือ: [2,3,5]

คำตอบ:


169

นี้ควรพิมพ์รายชื่อของตำแหน่งโดยไม่มี-1ที่สิ้นสุดว่าวิธีการแก้ปัญหาของปีเตอร์ Lawrey ได้มี

int index = word.indexOf(guess);
while (index >= 0) {
    System.out.println(index);
    index = word.indexOf(guess, index + 1);
}

นอกจากนี้ยังสามารถทำได้เป็นforลูป:

for (int index = word.indexOf(guess);
     index >= 0;
     index = word.indexOf(guess, index + 1))
{
    System.out.println(index);
}

[หมายเหตุ: หากguessสามารถยาวเกินอักขระเดี่ยวก็เป็นไปได้โดยการวิเคราะห์guessสตริงเพื่อให้วนซ้ำwordเร็วกว่าลูปด้านบน มาตรฐานสำหรับวิธีการดังกล่าวเป็นขั้นตอนวิธีการบอยเยอร์มัวร์ อย่างไรก็ตามเงื่อนไขที่ชอบใช้แนวทางดังกล่าวดูเหมือนจะไม่มีอยู่]


28

ลองทำดังต่อไปนี้ (ซึ่งไม่ได้พิมพ์ -1 ต่อท้าย!)

int index = word.indexOf(guess);
while(index >= 0) {
   System.out.println(index);
   index = word.indexOf(guess, index+1);
}

1
คุณมักจะพิมพ์ -1 ต่อท้าย
lukastymo

@ Peter ขอบคุณมากสำหรับคำตอบของคุณก็ดูเหมือนจะเป็นสิทธิ แต่นี้เป็นจริงวันแรกของฉันกับ Java ดังนั้นฉันเล็ก ๆ น้อย ๆ สับสนโดยผลสุดท้ายนี้ดูเหมือนว่าจะส่งออก -1 ในตอนท้ายผมดอนฯ ค่อนข้างเข้าใจว่าทำไม! ขอบคุณ !!
Trufa

@ Trufa: พิมพ์ -1 ต่อท้ายเสมอเนื่องจากindexOfส่งกลับค่า -1 เมื่อไม่พบอักขระ
ColinD

@Trufa - เหตุผลที่มันพิมพ์-1ในตอนท้ายก็คือdoห่วงรันร่างกายและแล้วพบว่าในการยุติindex == -1 while
Ted Hopp

@ColinD ส่วนที่ฉันได้รับสิ่งที่ฉันไม่เข้าใจคือสิ่งที่เกิดขึ้นกับฟังก์ชันเพื่อให้สิ่งนั้นเกิดขึ้นมัน "วนซ้ำ" ผ่านคำที่กำลังมองหาการเกิดขึ้นของตัวละครและจนกว่ามันจะไม่พบสิ่งที่ถูกต้อง เหรอ? และพิมพ์ดัชนีสุดท้ายของสิ่งที่ไม่พบ (-1) นั่นคือสิ่งที่เกิดขึ้นหรือไม่? (ไม่รู้ว่าออกมาถูกมั้ย)
Trufa

8
String string = "bannanas";
ArrayList<Integer> list = new ArrayList<Integer>();
char character = 'n';
for(int i = 0; i < string.length(); i++){
    if(string.charAt(i) == character){
       list.add(i);
    }
}

ผลลัพธ์จะใช้ในลักษณะนี้:

    for(Integer i : list){
        System.out.println(i);
    }

หรือเป็นอาร์เรย์:

list.toArray();


4

สิ่งนี้สามารถทำได้ในรูปแบบการทำงานกับ Java 9 โดยใช้นิพจน์ทั่วไป:

Pattern.compile(Pattern.quote(guess)) // sanitize input and create pattern
            .matcher(word) // create matcher
            .results()     // get the MatchResults, Java 9 method
            .map(MatchResult::start) // get the first index
            .collect(Collectors.toList()) // collect found indices into a list
    );

นี่คือ Kotlin Solution เพื่อเพิ่มตรรกะนี้เป็นวิธีการใหม่ในCharSequenceAPI โดยใช้วิธีการขยาย:

 // Extension method
fun CharSequence.indicesOf(input: String): List<Int> =
    Regex(Pattern.quote(input)) // build regex
        .findAll(this)          // get the matches
        .map { it.range.first } // get the index
        .toCollection(mutableListOf()) // collect the result as list

// call the methods as
"Banana".indicesOf("a") // [1, 3, 5]


1
String word = "bannanas";

String guess = "n";

String temp = word;

while(temp.indexOf(guess) != -1) {
     int index = temp.indexOf(guess);
     System.out.println(index);
     temp = temp.substring(index + 1);
}

แนวคิดทั่วไปถูกต้อง แต่word.substring(word)จะไม่รวบรวม : P
Peter Lawrey

1
ยังคงมีปัญหา: พิมพ์ต่อเนื่อง 2
POSIX_ME_HARDER

เอ้ยฉันต้อง javac ทุกอย่างที่ฉันโพสต์ที่นี่
asgs

0
    String input = "GATATATGCG";
    String substring = "G";
    String temp = input;
    String indexOF ="";
    int tempIntex=1;

    while(temp.indexOf(substring) != -1)
    {
        int index = temp.indexOf(substring);
        indexOF +=(index+tempIntex)+" ";
        tempIntex+=(index+1);
        temp = temp.substring(index + 1);
    }
    Log.e("indexOf ","" + indexOF);

0

นอกจากนี้หากคุณต้องการค้นหาดัชนีทั้งหมดของสตริงในสตริง

int index = word.indexOf(guess);
while (index >= 0) {
    System.out.println(index);
    index = word.indexOf(guess, index + guess.length());
}

สิ่งนี้น่าสนใจตรงที่ทำให้เกิดความคลุมเครือในความหมายของ "เหตุการณ์ทั้งหมด" หากguess เป็น"aba"และwordเป็นอยู่"ababa"จะไม่ชัดเจนว่าguessเกิดขึ้นครั้งหรือสองครั้งในword. (ฉันหมายถึงเป็นที่ชัดเจนว่าเราสามารถพบการguessเริ่มต้นที่ตำแหน่งที่แตกต่างกันสองตำแหน่ง แต่เนื่องจากเหตุการณ์ที่เกิดขึ้นทับซ้อนกันจึงไม่ชัดเจนว่าควรนับทั้งคู่หรือไม่) คำตอบนี้ใช้มุมมองที่ว่าเหตุการณ์ที่ทับซ้อนกันจะไม่ถูกนับว่าแตกต่างกัน แน่นอนเนื่องจากคำพูดของ OP แนะนำอย่างยิ่งว่าguessจะมีความยาว 1 เสมอความคลุมเครือจึงไม่เกิดขึ้น
Ted Hopp

0

ฉันมีปัญหานี้เช่นกันจนกระทั่งฉันคิดวิธีนี้ขึ้นมา

public static int[] indexesOf(String s, String flag) {
    int flagLen = flag.length();
    String current = s;
    int[] res = new int[s.length()];
    int count = 0;
    int base = 0;
    while(current.contains(flag)) {
        int index = current.indexOf(flag);
        res[count] = index + base;
        base += index + flagLen;
        current = current.substring(current.indexOf(flag) + flagLen, current.length());
        ++ count;
    }
    return Arrays.copyOf(res, count);
}

วิธีนี้สามารถใช้เพื่อค้นหาดัชนีของแฟล็กที่มีความยาวเท่าใดก็ได้ในสตริงตัวอย่างเช่น:

public class Main {

    public static void main(String[] args) {
        int[] indexes = indexesOf("Hello, yellow jello", "ll");

        // Prints [2, 9, 16]
        System.out.println(Arrays.toString(indexes));
    }

    public static int[] indexesOf(String s, String flag) {
        int flagLen = flag.length();
        String current = s;
        int[] res = new int[s.length()];
        int count = 0;
        int base = 0;
        while(current.contains(flag)) {
            int index = current.indexOf(flag);
            res[count] = index + base;
            base += index + flagLen;
            current = current.substring(current.indexOf(flag) + flagLen, current.length());
            ++ count;
        }
        return Arrays.copyOf(res, count);
    }
}

0

คลาสสำหรับการแยกสตริงที่ฉันคิดขึ้นมา มีการทดสอบสั้น ๆ ในตอนท้าย

SplitStringUtils.smartSplitToShorterStrings(String str, int maxLen, int maxParts) จะแบ่งด้วยช่องว่างโดยไม่ทำลายคำถ้าเป็นไปได้และหากไม่เป็นเช่นนั้นจะแบ่งตามดัชนีตาม maxLen

วิธีการอื่น ๆ ที่มีไว้เพื่อควบคุมวิธีการแยก: bruteSplitLimit(String str, int maxLen, int maxParts), spaceSplit(String str, int maxLen, int maxParts).

public class SplitStringUtils {

  public static String[] smartSplitToShorterStrings(String str, int maxLen, int maxParts) {
    if (str.length() <= maxLen) {
      return new String[] {str};
    }
    if (str.length() > maxLen*maxParts) {
      return bruteSplitLimit(str, maxLen, maxParts);
    }

    String[] res = spaceSplit(str, maxLen, maxParts);
    if (res != null) {
      return res;
    }

    return bruteSplitLimit(str, maxLen, maxParts);
  }

  public static String[] bruteSplitLimit(String str, int maxLen, int maxParts) {
    String[] bruteArr = bruteSplit(str, maxLen);
    String[] ret = Arrays.stream(bruteArr)
          .limit(maxParts)
          .collect(Collectors.toList())
          .toArray(new String[maxParts]);
    return ret;
  }

  public static String[] bruteSplit(String name, int maxLen) {
    List<String> res = new ArrayList<>();
    int start =0;
    int end = maxLen;
    while (end <= name.length()) {
      String substr = name.substring(start, end);
      res.add(substr);
      start = end;
      end +=maxLen;
    }
    String substr = name.substring(start, name.length());
    res.add(substr);
    return res.toArray(new String[res.size()]);
  }

  public static String[] spaceSplit(String str, int maxLen, int maxParts) {
    List<Integer> spaceIndexes = findSplitPoints(str, ' ');
    List<Integer> goodSplitIndexes = new ArrayList<>();
    int goodIndex = -1; 
    int curPartMax = maxLen;
    for (int i=0; i< spaceIndexes.size(); i++) {
      int idx = spaceIndexes.get(i);
      if (idx < curPartMax) {
        goodIndex = idx;
      } else {
        goodSplitIndexes.add(goodIndex+1);
        curPartMax = goodIndex+1+maxLen;
      }
    }
    if (goodSplitIndexes.get(goodSplitIndexes.size()-1) != str.length()) {
      goodSplitIndexes.add(str.length());
    }
    if (goodSplitIndexes.size()<=maxParts) {
      List<String> res = new ArrayList<>();
      int start = 0;
      for (int i=0; i<goodSplitIndexes.size(); i++) {
        int end = goodSplitIndexes.get(i);
        if (end-start > maxLen) {
          return null;
        }
        res.add(str.substring(start, end));
        start = end;
      }
      return res.toArray(new String[res.size()]);
    }
    return null;
  }


  private static List<Integer> findSplitPoints(String str, char c) {
    List<Integer> list = new ArrayList<Integer>();
    for (int i = 0; i < str.length(); i++) {
      if (str.charAt(i) == c) {
        list.add(i);
      }
    }
    list.add(str.length());
    return list;
  }
}

รหัสทดสอบง่ายๆ:

  public static void main(String[] args) {
    String [] testStrings = {
        "123",
        "123 123 123 1123 123 123 123 123 123 123",
        "123 54123 5123 513 54w567 3567 e56 73w45 63 567356 735687 4678 4678 u4678 u4678 56rt64w5 6546345",
        "1345678934576235784620957029356723578946",
        "12764444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444",
        "3463356 35673567567 3567 35 3567 35 675 653 673567 777777777777777777777777777777777777777777777777777777777777777777"
    };

    int max = 35;
    int maxparts = 2;


    for (String str : testStrings) {
      System.out.println("TEST\n    |"+str+"|");
      printSplitDetails(max, maxparts);
      String[] res = smartSplitToShorterStrings(str, max, maxparts);
      for (int i=0; i< res.length;i++) {
        System.out.println("  "+i+": "+res[i]);
      }
      System.out.println("===========================================================================================================================================================");
    }

  }

  static void printSplitDetails(int max, int maxparts) {
    System.out.print("  X: ");
    for (int i=0; i<max*maxparts; i++) {
      if (i%max == 0) {
        System.out.print("|");
      } else {
        System.out.print("-");
      }
    }
    System.out.println();
  }

0

นี่คือโซลูชัน java 8

public int[] solution (String s, String subString){
        int initialIndex = s.indexOf(subString);
        List<Integer> indexList = new ArrayList<>();
        while (initialIndex >=0){
            indexList.add(initialIndex);
            initialIndex = s.indexOf(subString, initialIndex+1);
        }
        int [] intA = indexList.stream().mapToInt(i->i).toArray();
        return intA;
    }

-1

สามารถทำได้โดยการวนซ้ำmyStringและเปลี่ยนfromIndexพารามิเตอร์ในindexOf():

  int currentIndex = 0;

  while (
    myString.indexOf(
      mySubstring,
      currentIndex) >= 0) {

    System.out.println(currentIndex);

    currentIndex++;
  }

คุณลองเรียกใช้รหัสนี้หรือยัง มันจะพิมพ์ทุกตำแหน่ง (0, 1, 2, ... ) จนถึงดัชนีของการเกิดครั้งสุดท้ายmySubstringโดยไม่คำนึงว่าmySubstringจะพบได้ในแต่ละตำแหน่งหรือไม่ ไม่ใช่สิ่งที่ OP ต้องการ ..
Ted Hopp

-4

ลองทำตามนี้

String str = "helloslkhellodjladfjhello";
String findStr = "hello";

System.out.println(StringUtils.countMatches(str, findStr));

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

แม้ว่ารหัสนี้อาจตอบคำถามได้ แต่การให้บริบทเพิ่มเติมเกี่ยวกับวิธีการและ / หรือเหตุผลในการแก้ปัญหาจะช่วยเพิ่มมูลค่าในระยะยาวของคำตอบ
Nic3500

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