2016-04-04 15 views
0

Bu projeyle ilgili bir sorun yaşıyorum. Temel dayanak, kullanıcı bir deyim girer ve herhangi bir yinelenen sözcük bulması ve kaç tane olduğu varsayılır. Böyle merhaba merhaba merhaba merhaba merhabaJava, öğeleri bir ArrayList öğesinden kaldırma

bunun için çıkış olur ... gibi sadece bir kelime birden çok kez girerken

Sorunum;

"There are 2 duplicates of the word "hello" in the phrase you entered." 
"There are 1 duplicates of the word "hello" in the phrase you entered." 

Bu, yalnızca bu gibi durumlarda olduğu anlaşılıyor. Dışarıya atılan birden fazla kelimeyle rastgele bir ifadeyi girersem, doğru cevabı gösterir. Sorunun yinelenen kelimeleri kaldırmasıyla ve ifade ile kaç kez yinelendiği ile ilgili bir şey olduğunu düşünüyorum, ama kafamı etrafına saramam. Her yerde baskı çizgileri ekledim ve her türlü yolu yineleyen zamanları değiştirdim, bunu bir Java Görüntüleyicide gerçekleştirdim ve yine de tam olarak bulamadım. Herhangi bir yardım büyük beğeni topluyor!

Bu, çevrimiçi Java kursumun bir ödevi içindir, ancak bu sadece öğrenme/uygulama için ana başıma gitmemektedir. Sadece yardım etmek için cevap aramıyorum. benim kodunu düzenledi bazı önerilere dayalı

public class DuplicateWords { 

public static void main(String[] args) { 

    List<String> inputList = new ArrayList<String>(); 
    List<String> finalList = new ArrayList<String>(); 

    int duplicateCounter; 
    String duplicateStr = ""; 
    Scanner scan = new Scanner(System.in); 

    System.out.println("Enter a sentence to determine duplicate words entered: "); 
    String inputValue = scan.nextLine(); 
    inputValue = inputValue.toLowerCase(); 
    inputList = Arrays.asList(inputValue.split("\\s+")); 
    finalList.addAll(inputList); 


    for(int i = 0; i < inputList.size(); i++) { 
     duplicateCounter = 0; 
     for(int j = i + 1; j < finalList.size(); j++) { 
      if(finalList.get(i).equalsIgnoreCase(finalList.get(j)) 
        && !finalList.get(i).equals("!") && !finalList.get(i).equals(".") 
        && !finalList.get(i).equals(":") && !finalList.get(i).equals(";") 
        && !finalList.get(i).equals(",") && !finalList.get(i).equals("\"") 
        && !finalList.get(i).equals("?")) { 
       duplicateCounter++; 
       duplicateStr = finalList.get(i).toUpperCase(); 
      } 
      if(finalList.get(i).equalsIgnoreCase(finalList.get(j))) { 
       finalList.remove(j); 
      } 

     } 
     if(duplicateCounter > 0) { 
      System.out.printf("There are %s duplicates of the word \"%s\" in the phrase you entered.", duplicateCounter, duplicateStr); 
      System.out.println(); 
     } 
    }  
} 
} 

, ama ben doğru yönde gidiyorum emin değilim

String previous = ""; 

    for(Iterator<String> i = inputList.iterator(); i.hasNext();) { 
     String current = i.next(); 
     duplicateCounter = 0; 
     for(int j = + 1; j < finalList.size(); j++) { 
      if(current.equalsIgnoreCase(finalList.get(j)) 
        && !current.equals("!") && !current.equals(".") 
        && !current.equals(":") && !current.equals(";") 
        && !current.equals(",") && !current.equals("\"") 
        && !current.equals("?")) { 
       duplicateCounter++; 
       duplicateStr = current.toUpperCase(); 
      } 
      if(current.equals(previous)) { 
       i.remove(); 
      } 

     } 
     if(duplicateCounter > 0) { 
      System.out.printf("There are %s duplicates of the word \"%s\" in the phrase you entered.", duplicateCounter, duplicateStr); 
      System.out.println(); 
     } 
    } 
+2

. Bu beklenmedik davranışlara neden olur. Kullanmak için güvenli bir yöntem 'Iterator.remove()', bkz. Http://stackoverflow.com/a/223929/4190526 –

+0

Öğelerini kaldırırken bir diziyi yinelemek isterseniz, sonundan başlamanızı öneririz. diziyi ve en üste yineleyin. – annena

cevap

1

Senin sorunun, bir öğeyi kaldırdığınızda, hala indeksi artırır, bu yüzden bir sonraki öğeyi olacağını atladıklarınıza olmasıdır. kısaltılmış Forma, kod şudur: doğrudan böyle bir öğeyi kaldırma sağa tüm öğeleri neden olduğu

kaldır çağrıldıktan sonra
for (int j = i + 1; j < finalList.size(); j++) { 
    String next = finalList.get(i); 
    if (some test on next) 
     finalList.remove(next); 
} 

, "sonraki" öğesi, aynı dizinde olacak 1 yerde, karıştırılacak olan boşluğu doldurmak için kaldı. düzeltmek için, çıkardıktan sonra bu satırı eklemek gerekir: sorununuzu çözmek istiyorum

i--; 

Ancak bunu yapmak için daha temiz bir yolu var:

String previous = ""; 
for (Iterator<String> i = inputList.iterator(); i.hasNext();) { 
    String current = i.next(); 
    if (current.equals(previous)) { 
     i.remove(); // removes current item 
    } 
    previous = current; 
} 

inputList

şimdi kaldırıldı tüm komşu çiftleri vardır.

tüm çiftleri kaldırmak için: Eğer ağrı gibi

List<String> finalList = inputList.stream().distinct().collect(Collectors.toList()); 

, bu "el" yapın: ondan öğeleri kaldırarak ederken bir ArrayList yineleme olan

Set<String> duplicates = new HashSet<>(); // sets are unique 
for (Iterator<String> i = inputList.iterator(); i.hasNext();) 
    if (!duplicates.add(i.next())) // add returns true if the set changed 
     i.remove(); // removes current item 
+0

Yani, yukarıdaki gibi Iterator kullanırken, i 'i bir sonraki atandınız ve sonra i yerine bir sonraki noktayı kullanırım, değil mi? İç döngü için de bir yineleyici yaklaşımı mı kullanırdım? – NoobCoderChick

+0

@ sjud9227 Daha net hale getirmek ve size tüm şeyi göstermek için "uygun" kodu düzenledim. En önemli fark, 'iterator.remove()' 'iterator.next()' ifadesinin ne döndüğünü değiştirmemesidir. – Bohemian

+0

Hala biraz kafam karışık, üzgünüm 7 saat bilgisayarımın üzerinde beynim kızartılıyor. Yani demek istediğin, döngü için iç (j) ye ihtiyacım yok mu? – NoobCoderChick

0

Eğer finalList için inputList eklemeden önce, herhangi bir yinelenen kaldırmak inputList'dan öğeler.

+0

Girişlistesinden hiçbir şey kaldıramıyorum çünkü kullanıcı girdisini ayırmak için Arrays.asList kullanıyorum ve List bu noktada değiştirilemez. – NoobCoderChick

1

Her sözcükle bir Map<String, Integer> doldurmaya başlıyorum; Bir sözcükle her karşılaştığınızda Integer'u artırın.

String inputValue = scan.nextLine().toLowerCase(); 
String[] words = inputValue.split("\\s+"); 
Map<String, Integer> countMap = new HashMap<>(); 
for (String word : words) { 
    Integer current = countMap.get(word); 
    int v = (current == null) ? 1 : current + 1; 
    countMap.put(word, v); 
} 

gibi bir şey Sonra MapentrySet yineleme ve sayım 1 daha büyük olduğu her key (word) görüntüleyebilir. senin koduyla bir şey gibi

String msgFormat = "There are %d duplicates of the word \"%s\" in " 
     + "the phrase you entered.%n"; 
for (Map.Entry<String, Integer> entry : countMap.entrySet()) { 
    if (entry.getValue() > 1) { 
     System.out.printf(msgFormat, entry.getValue(), entry.getKey()); 
    } 
} 
+0

Her bir kopya için sonucu yazdırırken aynı problemi olmaz mıydı? "Merhaba", 4 kopya yazdı ve daha sonra bir sonraki geçişi "merhaba" nın 3 kopyası olduğunu söyleyebilirdi. Bu yüzden yinelenenleri listeden çıkardığım sırada kaldırmaya başladım. – NoobCoderChick

+0

@ sjud9227 Hayır. Çünkü her kelime bir anahtardır ve bu nedenle "Harita" da ** benzersiz ** olur. –

+0

Tamam. Harita hakkında bir çok şey anlamadım ve bunu bu gece açmak zorundayım, bugün Harita'yı atlayabilir ve uygulamaya geri dönebilirim. – NoobCoderChick