2016-07-25 97 views
-3

我有一個排序後的數組,我想檢查重複的entrys。問題是我需要知道重複的位置是多維數組,我需要刪除第二個條目。另外最後,我必須有一個數組填充值,所以只是用一些啞元覆蓋重複項將不起作用。我已經閱讀了有關Array.utils的技巧,但我不想導入任何其他庫文件,而且Array.utils不能識別,因此我必須導入該文件。檢查排序後的數組是否重複

我也試着寫一個小功能自己

 Integer iIndex = 1; 
    while (keepRunning2){ 
     if(phoneNameNumber[iIndex][0].equals(phoneNameNumber[iIndex-1][0])){ 
      keepRunning = true; 
      tmp = new String[phoneNameNumber.length-1][2]; 
      int k = 0; 
      int t=0; 
      while(keepRunning){ 
       Log.wtf("running",String.valueOf(iIndex) + ":" + String.valueOf(k)); 
       tmp[t][0] = phoneNameNumber[k][0]; 
       tmp[t][1] = phoneNameNumber[k][1]; 
       if(k!=i-1){ 
        k++; 
        t++; 
       }else{ 
        k=k+2; 
        t++; 
       } 
       if(t==tmp.length-1) 
        keepRunning=false; 

      } 
      phoneNameNumber = null; 
      phoneNameNumber = new String[tmp.length][2]; 
      phoneNameNumber = tmp; 
     } 
     if(!(iIndex < phoneNameNumber.length-1)){ 
      keepRunning2 = false; 
     } 
     iIndex++; 
    } 

Buuuut ...首先,它需要像10年的時間完成這一點,因爲這是一個應用程序的UI,你可以看到,它應該是由於某種原因,在處理完所有這些後,它會跳回到像keeppRunning2'd永遠不會設置爲false的狀態。

那麼有人知道一個解決方案嗎?

,如果某人想知道數據來自:繼承人的活動

import android.app.ActionBar; 
import android.app.Activity; 
import android.app.DialogFragment; 
import android.content.ContentResolver; 
import android.content.Intent; 
import android.database.Cursor; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.provider.ContactsContract; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.CheckBox; 
import android.widget.CheckedTextView; 
import android.widget.EditText; 
import android.widget.LinearLayout; 
import android.widget.RadioGroup; 
import android.widget.Spinner; 
import android.widget.TextView; 
import android.widget.Toast; 

import java.sql.Array; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Comparator; 
import java.util.List; 
import java.util.concurrent.ExecutionException; 

/** 
* Created by **** on 19.07.2016. 
*/ 
public class newChatActivity extends Activity implements  View.OnClickListener,AdapterView.OnItemSelectedListener{ 

Button bCreateChat; 
Button bCancelChat; 
EditText tchat_name; 
//EditText tmembers; 
CheckBox cBoxPrivateChat; 
Spinner memberSpinner; 
String members = ""; 
String lastContactName = ""; 
List<String> nameList,number; 
String[][]phoneNameNumber,tmp; 
String[] sortedNames; 
Integer i = 0; 
Integer memberCount = 0; 
Boolean keepRunning = true; 
Boolean keepRunning2 = true; 

private static final String[] PROJECTION = new String[] { 
     ContactsContract.CommonDataKinds.Phone.CONTACT_ID, 
     ContactsContract.Contacts.DISPLAY_NAME, 
     ContactsContract.CommonDataKinds.Phone.NUMBER 
}; 



@Override 
public void onCreate(Bundle savedInstanceState){ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.new_chat); 
    setTitle("Add New Chat"); 

    bCreateChat = (Button) findViewById(R.id.bCreateChat); 
    bCancelChat = (Button) findViewById(R.id.bChatCance); 
    tchat_name = (EditText) findViewById(R.id.tchat_name); 
    cBoxPrivateChat = (CheckBox) findViewById(R.id.cBoxprivChat); 
    memberSpinner = (Spinner) findViewById(R.id.memberSpinner); 


    bCreateChat.setOnClickListener(this); 
    bCancelChat.setOnClickListener(this); 

    loadAllContacts(); 
    sortedNames = new String[phoneNameNumber.length]; 
    Integer iIndex = 1; 
    while (keepRunning2){ 
     if(phoneNameNumber[iIndex][0].equals(phoneNameNumber[iIndex-1][0])){ 
      keepRunning = true; 
      tmp = new String[phoneNameNumber.length-1][2]; 
      int k = 0; 
      int t=0; 
      while(keepRunning){ 
       Log.wtf("running",String.valueOf(iIndex) + ":" + String.valueOf(k)); 
       tmp[t][0] = phoneNameNumber[k][0]; 
       tmp[t][1] = phoneNameNumber[k][1]; 
       if(k!=i-1){ 
        k++; 
        t++; 
       }else{ 
        k=k+2; 
        t++; 
       } 
       if(t==tmp.length-1) 
        keepRunning=false; 


      } 
      phoneNameNumber = null; 
      phoneNameNumber = new String[tmp.length][2]; 
      phoneNameNumber = tmp; 
     } 
     if(!(iIndex < phoneNameNumber.length-1)){ 
      keepRunning2 = false; 
     } 
     iIndex++; 
    } 

    for(int i = 0;i<phoneNameNumber.length;i++){ 
     sortedNames[i] = phoneNameNumber[i][0]; 
    } 
    ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,sortedNames); 
    spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
    memberSpinner.setAdapter(spinnerAdapter); 
    memberSpinner.setOnItemSelectedListener(this); 



} 


@Override 
public void onClick(View v) { 
    switch (v.getId()){ 
     case R.id.bCreateChat: 
       if (!tchat_name.getText().toString().isEmpty()&&!members.isEmpty()) { 
        if(cBoxPrivateChat.isChecked()){ 
         createChat("name=" + tchat_name.getText().toString() + "&members=" + members + ScrollingActivity.Identifier + "#"); 
        } 
       } else{ 
        Toast.makeText(this,"Keine Daten Eingegeben",Toast.LENGTH_SHORT).show(); 
       } 
      break; 
     case R.id.bChatCance: 
      this.finish(); 
      break; 
     default: 
      if(v.getId() > 2000000){ 
       members = members.replace("#" + number.get(v.getId() - 2000000) + "#",""); 
       TextView delText = (TextView) findViewById(v.getId()); 
       delText.setVisibility(View.GONE); 
       memberCount = memberCount - 1; 
       if(memberCount <= 1){ 
        cBoxPrivateChat.setEnabled(true); 
       } 
      } 
    } 
} 

public void createChat(String Data){ 
    try { 
     Boolean b = new createNewCHat().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,ScrollingActivity.ServerLocation + "/alterChat.php", Data).get(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     e.printStackTrace(); 
    } 
    Intent intent = new Intent(getApplicationContext(), ScrollingActivity.class); 
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
    intent.putExtra("EXIT", true); 
    startActivity(intent); 
} 

@Override 
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
    if(position != 0 && !cBoxPrivateChat.isChecked()) { 
     members = members + "#" + number.get(position) + "#"; 
     TextView MemberText = new TextView(this); 
     MemberText.setId(2000000 + position); 
     MemberText.setText(phoneNameNumber[position][0] + " " + phoneNameNumber[position][1]); 
     LinearLayout memberLayout = (LinearLayout) findViewById(R.id.membersLayout); 
     RadioGroup.LayoutParams params = new RadioGroup.LayoutParams(RadioGroup.LayoutParams.MATCH_PARENT, 100); 
     memberLayout.addView(MemberText, params); 
     MemberText.setOnClickListener(this); 
     memberCount++; 
     if(memberCount > 1){ 
      cBoxPrivateChat.setEnabled(false); 
      cBoxPrivateChat.setChecked(false); 
     } 
    } else if(position != 0 && cBoxPrivateChat.isChecked() && members.equals("")){ 
     members = members + "#" + number.get(position) + "#"; 
     TextView MemberText = new TextView(this); 
     MemberText.setId(2000000 + position); 
     MemberText.setText(phoneNameNumber[position][0] + " " + phoneNameNumber[position][1]); 
     LinearLayout memberLayout = (LinearLayout) findViewById(R.id.membersLayout); 
     RadioGroup.LayoutParams params = new RadioGroup.LayoutParams(RadioGroup.LayoutParams.MATCH_PARENT, 100); 
     memberLayout.addView(MemberText, params); 
     MemberText.setOnClickListener(this); 
     memberCount++; 
    } 
} 

@Override 
public void onNothingSelected(AdapterView<?> parent) { 

} 


public void loadAllContacts(){ 
    nameList = new ArrayList<String>(); 
    number = new ArrayList<String>(); 
    ContentResolver cr = getContentResolver(); 
    Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null); 
    if (cursor != null) { 
     try { 
      final int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); 
      final int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER); 


      nameList.add(0,"Select chat members"); 
      number.add(0,""); 

      while (cursor.moveToNext()) { 
       if(!cursor.getString(nameIndex).equals(lastContactName)){ 
        nameList.add(cursor.getString(nameIndex)); 
        number.add(cursor.getString(numberIndex)); 
        lastContactName = cursor.getString(nameIndex); 
       } 
      } 
     } finally { 
      cursor.close(); 

     } 
     phoneNameNumber = new String[nameList.size()][2]; 

     for(int i = 0; i<nameList.size();i++){ 
      phoneNameNumber[i][0] = nameList.get(i); 
      phoneNameNumber[i][1] = number.get(i); 
     } 

     Arrays.sort(phoneNameNumber, new Comparator<String[]>() { 
      @Override 
      public int compare(final String[] entry1, final String[] entry2) { 
       final String time1 = entry1[0]; 
       final String time2 = entry2[0]; 
       return time1.compareTo(time2); 
      } 
     }); 

    } 

} 
} 

噢,順便說一下是否有人知道爲什麼有數組中的重複?因爲如果我簡單地使用微調列表上的列表名稱,我沒有任何副本

+0

'而(keepRunning2){':'沒有定義keepRunning2'。 (我可以想象一個,但'phoneNameNumber'還沒有被定義太......你可以提供一些假的值,你想要刪除,以及你期望的)。順便說一句,如果我甚至會嘗試回答這個問題,首先我需要知道,爲什麼要使用數組,而不是某些List/Map/Set,而不是用於擦除元素的地方。 – Ped7g

+0

編程時最重要的是數據的結構。你能提供一個數據結構如何的例子嗎? –

+0

以及我確實分配'電話名稱號碼3次,因爲我還沒有完全理解數組是如何工作的。所以第一個是刪除舊的數組(因爲我不想讓一些舊的數據仍在那裏),那麼我想初始化數組,然後我分配一個值。 其實我正在學習是 - 一週?沒有 我既不使用教程,也沒有講課任何代替我的知識一點點,決定建立一個應用程序出了什麼事情我知道,現在我試圖展開了解到 也如果妳希望看到一些非常糟糕的代碼 - 我包括 – BAAAZINGA

回答

0

所以你可能想一些這樣的功能:

(但我不明白你的「我需要知道重複了」 ......爲什麼,也是你的代碼不使用其他尺寸?以任何方式,只有[0]進行比較,所以,我認爲模擬天生在我的代碼太多,但也許這是不是你想要的嗎?)

import java.util.Arrays; // Maybe all of your problem is that you had typo in import? 
// This is language standard stuff, available everywhere IMHO 

    /** 
    * Removes duplicates and nulls from sorted array, first item (sortedArray[i][0]) is considered 
    * for duplicates search, rest of values sortedArray[i][1..n] is not considered at all. 
    * 
    * @param sortedArray 
    *   sorted 2D String array, can have any 1 <= length in second dimension. 
    * @return items with duplicate in [i][0] or null will be removed from result array. 
    */ 
    public static String[][] removeDuplicateOrNullItems(final String[][] sortedArray) { 
     // validate input 
     if (null == sortedArray || sortedArray.length <= 1) { 
      return sortedArray; // garbage in, garbage out 
     } 
     // search for first duplicate (if any) 
     int i = 0; 
     while (++i < sortedArray.length) { 
      if (null == sortedArray[i][0] || sortedArray[i][0].equals(sortedArray[i - 1][0])) { 
       break; 
      } 
     } 
     if (i == sortedArray.length) { 
      return sortedArray; // no duplicate found, return input 
     } 
     // First duplicate is at index i, now compact the rest of array content (overwriting dupes) 
     int newi = i; // will serve both as count of unique values, and compact-writing index 
     while (++i < sortedArray.length) { 
      if (null == sortedArray[i][0] || sortedArray[i][0].equals(sortedArray[i - 1][0])) { 
       continue; // another duplicate, skip this one 
      } 
      sortedArray[newi++] = sortedArray[i]; // valid value, compact it 
     } 
     return Arrays.copyOf(sortedArray, newi); // return the compacted result 
    } 

// demo how to call it: 

     String[][] in = {{"A1", "A2"}, {"A1", "dupA"}, {null, null}, {"B1", "B2"}, {"B1", "dupB1"}, {"B1", "dupB2"}, {"C1", "C2"}}; 
//  String[][] in = {{"A1", "A2", "A3"}, {"B1", "B2", "B3"}}; 
//  String[][] in = null; 

     String[][] out = removeDuplicateOrNullItems(in); 

我想評論這一點給你的想法它在做什麼......雖然使用調試器並逐行逐行執行可能會幫助更多。


如果你真的想避免java.util.Arrays中,那麼最後return Arrays.copyOf...應與此代替:

final String[][] result = new String[newi][sortedArray[0].length]; 
    for (i = 0; i < newi; ++i) result[i] = sortedArray[i]; 
    return result; 

補充說:
那些3分配:

 phoneNameNumber = null; 
     phoneNameNumber = new String[tmp.length][2]; 
     phoneNameNumber = tmp; 

我不知道你已經知道關於編夯實,所以這可能是困難的。

phoneNameNumberString[][]類型,它是存放在內存中的地址(指針)類型,數組存儲在哪裏(維數不重要ATM)。

所以你首先將它設置爲null,然後到新分配的空間,最後到tmp指向的空間(與tmp共享相同的數組)。分配新內存的第二行是無用的,它將被第三行直接覆蓋,新分配的內存將用於GC(垃圾收集器)。

如果你想要的值從tmp複製到內存中的新分配的區域(一個真正的副本),你就必須爲循環做了,並分配phoneNameNumber[i][j] = tmp[i][j];。然後它將與tmp共享只有指向String本身的指針,這在Java中是可以使用的,因爲String是不可變的(不能更改該值,因此如果保留一個字符串的地址,則可以確定它的內容沒有即使代碼的其他部分與該指針一起工作也是如此)。

如果你這樣做只phoneNameNumber[i] = tmp[i];複製它,它看起來一見鍾情新phoneNameNumber相同(值是相同tmp但有區別,現在phoneNameNumbertmp也將分享這兩個字符串內微小陣列,因此該副本後,如果你會做tmp[0][1] = null;,該phoneNameNumber[0][1]會突然包含null太(因爲內存存儲這些指向字符串該區域是共享的,所以你有寫空指針兩個變量)。

或複製(true copy)數組使用java.util.Arrays.copy***方法。

將其設置爲null的第一行實際上有時用於Java程序中,以標記GC的某些內存爲「待發布」,如果您知道不再使用該內存。

當您用另一個指針立即覆蓋phoneNameNumber時,這是無用的,如果您只是直接將tmp指定給它(丟失舊值=準備好GC),GC也會收集原始內存。實際上,在這種情況下,性能明智的做法是中間步驟將舊值歸零,這會損害JVM + GC,因爲它解析了兩個分配而不是一個分配,結果相同。如你所見,我不關心我是複製還是共享原始數組的一部分,使用哪一個更簡單。因此,該方法的編寫方式是修改原始輸入。如果你想保持它的完整(和接收結果不同的陣列中),你就必須與輸入數組的副本,以調用它,讓它亂用的副本:
String[][] out = removeDuplicateOrNullItems(Arrays.copyOf(in, in.length));
編輯:BUG ^^這copyOf或in.clone()不是深層複製,在所有維度上創建副本 ,但只創建上層數組的副本,共享下面的所有內容。

實施例的代碼:

// INIT 

String[][] in = {{"A1", "A2"}, {"B1", "B2"}}; 
// in is array of 2 references (pointers) at String[] value. 
// Let's say [email protected] = [@r1, @r2] (at address @adr1 in memory) 
// @r1 = array of two references to Strings [@"A1", @"A2"], @r2 = [@"B1", @"B2"] 
String[][] inCopy = in.clone(); 
// inCopy has copy of top level array (content of [email protected]) at address @adr2 
// [email protected] = [@r1, @r2]; so this is in new memory, 
// but the values are old @r1 and @r2, sharing the second level arrays with "in" 

// modification CASE 1 

String[] x = {"X1", "X2"}; // [email protected] = [@"X1", @"X2"] 
in[0] = x; 
// [email protected] = [[email protected], @r2], so in = [[X1, X2], [B1, B2]] 
// [email protected] = [@r1, @r2], so inCopy = [[A1, A2], [B1, B2]] 

// modification CASE 2 (on deeper level, where clone/copyOf didn't create copy) 

in[1][0] = "X"; // @r2[0] modified to contain @"X"; 
// [email protected] = [[email protected], @r2], @r2 = [@"X", @"B2"], in = [[X1, X2], [X, B2]] 
// [email protected] = [@r1, @r2] (same @r2!), so inCopy = [[A1, A2], [X, B2]] 

正如可以看到,在第二種情況下,InCopy中通過在改性而改性的[1] [0]。爲了防止這種情況,你必須每深度多維數組複製:

String[][] in = {{"A1", "A2"}, {"B1", "B2"}}; 
String[][] inCopy = new String[in.length][in[0].length]; 
// inner arrays of inCopy are cloned to new memory, not shared with "in" 
for (int i = 0; i < in.length; ++i) { 
    inCopy[i] = in[i].clone(); 
} 

但你可以以此爲警示,它並不難創造你的假設出現了重大失誤。 :/總是測試你的代碼......:D(單元測試的自動化測試對於這種情況是完美的)。在編寫第一個良好的版本之後,它也不會因爲一步一步地在調試器中逐步完成而感到痛苦,只是爲了驗證它是否按照您的預期工作(加上它有助於學習很多)。


通常,當你創建你自己的方法,這是一個好一點作用於輸入爲永恆不變的價值,並不能修改它們(在理想的世界我的方法會在一開始創建數組的副本)。這會導致後來出現更少的突發錯誤,當你調用你的API時,會認爲它只會將修改後的數組作爲新副本返回,但不會修改輸入。 (Java的Date類是出了名的追趕我猝不及防,當我問存儲UI一定的價值,並做一些計算它,看看是否例如日期將14天到期,然後我不知道爲什麼在UI的價值沒有變化(像我一樣在原來的內存計算,而不是複製它)。String是不變的,所以當你改變一個字符串的一些新的價值,你可以打賭,你沒有收到新的指針,如果其他代碼直接持有舊,它仍然看到舊的字符串=對程序員不斷的匆匆不感到驚訝

嗯......這太長了如果你沒有弄清楚我在說什麼,試着搜索計算機內存是如何工作的,什麼是內存分配,然後在Java中,如何存儲變量found something here, looks like free lecture notes from uni course。如果你是編程新手,它可能是q一開始你會混淆視聽,然後搜索一些描述計算機工作原理的小孩書籍,或者一些關於編程的早期書籍(1970-1990年代),它應該爲你理解內部發生的事情提供了很好的基礎,當你閱讀更多有關JVM 。

+0

嗯非常感謝這就是樂於助人的極端和老實說,我從很多教訓(altough我的大腦並從所有變量傷害內存和複製或deepcoopy stuuf XD)剛你用不變的價值來表達什麼? – BAAAZINGA

+0

簡而言之:不可變的類 - >你用值來實例化它,比如'String s =「hello」;'就是這樣,那個特定的Java String實例不會改變。如果你改變該字符串中的某個字符,它將在內部被複制到新的內存中,並被修改,並且會創建一個新的字符串實例(也被凍結)。所以如果你用String做了很多修改,你實際上是在複製一些內存,這就是爲什麼'StringBuilder'存在於Java中的原因。 (以及爲什麼你永遠都不應該針對Java'String'對C++'std :: string'進行基準測試,因爲這就像比較飛機和汽車)。 – Ped7g

+0

@BAAAZINGA:使用immutables(String/BigDecimal/...)不太容易出現程序員的錯誤(意外使用已修改的值,期望舊的或其他方式),並且通常會導致更簡單/更易於讀取源。並且更容易創建多線程版本。額外的成本是所有這些寫入時複製操作的性能(如果不能避免的話)。與尋找一些奇怪的錯誤相比,這通常成本很低。無論如何,使用互聯網。 (我正在學習無編碼(紙+筆和每週4小時HW時間)和無線(僅限書本))的代碼。也許是更好,更少分心。 :d – Ped7g

0

Java是一種功能強大的語言,因爲它具有有用的庫。我建議你使用ArrayList,因爲它會提高你的效率,性能和複雜性。

如果你想解決這種問題而不使用這些庫,這是我能想到的最好的方法。

// I don't know what's your phoneNameNumber, but I assume it is 2D string array: 
String[][] phoneNameNumber = new String[][]; 
String duplicatedIndicesString = ""; 

// Loop through phoneNameNumber 
for (int i=0; i<phoneNameNumber.length; i++) { 
    // Find duplicates 
    for (int i2=0; i<phoneNameNumber.length; i2++) { 
     boolean duplicated = true; 

     for (int j=0; j<phoneNameNumber[i2].length; j++) { 
      if (phoneNameNumber[i][j].equals(phoneNameNumber[i2].j) == false) { 
       // Not duplicate for this i2 
       duplicated = false; 
       break; 
      } 
     } 

     if(duplicated == true) { 
      duplicatedIndicesString += i2; 
      if (i2!=phoneNameNumber.length-1) { 
       // Store duplicated index for later dynamic allocation.. 
       duplicatedIndicesString += ","; 
      } 
     } 
    } 
} 

// Now let's copy results to a new array. 
String[] duplicatedIndicesStringArray = duplicatedIndicesString.split(","); 
String[][] resultPhoneNameNumber = new String[phoneNameNumber.length - dupicatedIndices.length][2]; 
int resultIndex = 0; 

for (int i=0; i<phoneNameNumber.length; i++) { 
    boolean duplicated = false; 

    for (j=0; j<duplicatedIndicesStringArray.length; j++) { 
     if (Integer.parseInt(duplicatedIndicesStringArray[j]) == i) { 
      duplicated = true; 
      break; 
     } 
    } 

    if (duplicated == false) { 
     resultPhoneNameNumber[resultIndex] = phoneNameNumber[i]; 
     resultIndex++; 
    } 
} 

這可能是我寫了一段時間的最醜陋的代碼。我這樣做是因爲我喝了太多早晨的咖啡。在編碼之前考慮一下。