2012-01-10 51 views
2

我試圖在多個二維數組中找到類似的行,如my previous post中所述。對於下面給出的例子,答案是false, true,,但它應該是false, false用於在二維數組中找到相似行的代碼

另一個非常重要的問題是如何將此代碼調整爲具有不同行數的數組

我非常感謝任何幫助。謝謝。

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Map; 

public class Test { 

    public static void main(String[] args) { 
     ArrayList<Integer[]> array1 = new ArrayList<Integer[]>(); 
     ArrayList<Integer[]> array2 = new ArrayList<Integer[]>(); 
     ArrayList<Integer[]> array3 = new ArrayList<Integer[]>(); 
     array1.add(new Integer[]{1,2,3}); array1.add(new Integer[]{1,0,3}); 
     array2.add(new Integer[]{1,0,3}); array2.add(new Integer[]{0,0,3}); 
     array3.add(new Integer[]{1,2,3}); array3.add(new Integer[]{0,3,3}); 
     for (int i=0; i<array1.size(); i++) { 
      boolean answ = equalRows(array1.get(i),array2.get(i),array3.get(i)); 
      System.out.println(answ); 
     } 
    } 

    static class Row extends Object { 
     private int value; 

     public Row(int val) { 
      this.value = val; 
     } 

     @Override 
     public boolean equals(Object obj) { 
      if(this == obj) 
       return true; 
      if((obj == null) || (obj.getClass() != this.getClass())) 
       return false; 
      // object must be Row at this point 
      Row row = (Row)obj; 
       return (value == row.value); 
     } 

     @Override 
     public int hashCode() { 
      return this.value; 
     } 
    } 

    private static Map<Row, Integer> map(Integer[] row) { 
      Map<Row, Integer> rowMap = new HashMap<Row, Integer>(); 
      for (int i=0; i<row.length; i++) 
       rowMap.put(new Row(row[i]), i); 
      return rowMap; 
    } 

    private static boolean equalRows(Integer[] row1, Integer[] row2, Integer[] row3){ 
      Map<Row, Integer> map1 = map(row1); 
      Map<Row, Integer> map2 = map(row2); 

      for (int i=0; i<row3.length; i++){ 
       Row row = new Row(row3[i]); 
       Integer result1 = map1.get(row); 
       Integer result2 = map2.get(row); 
       if (result1 == null || result2 == null) { 
        return false; 
       } 
      } 
     return true; 
    } 

} 

編輯#1 在第一測試I'm比較{1,2,3},{1,0,3}和{1,2,3}。第二個:{1,0,3},{0,0,3},{0,3,3}。第二行的問題是{0,0,3}和{0,3,3}的處理方式爲{0,3}。我不知道如何修改代碼來在{0,0,3}和{0,3,3}之間進行區分(我仍然應該使用HashMap)。

編輯#2 這個想法是,我首先從array1和array2中取出行,然後將它們放到地圖中。然後我從array3中取出一行並嘗試在地圖中找到它。如果我無法在這些地圖中找到它,那麼這意味着行不相似。

回答

1

要比較兩個數組,忽略空值,你可以有

public static <T> boolean equalsExceptForNulls(T[] ts1, T[] ts2) { 
    if (ts1.length != ts2.length) return false; 
    for(int i = 0; i < ts1.length; i++) { 
     T t1 = ts1[i], t2 = ts2[i]; 
     if (t1 != null && t2 != null && !t1.equals(t2)) 
      return false; 
    } 
    return true; 
} 

public static <T> boolean equalsExceptForNulls3(T[] ts1, T[] ts2, T[] ts3) { 
    return equalsExceptForNulls(ts1, ts2) && 
      equalsExceptForNulls(ts1, ts3) && 
      equalsExceptForNulls(ts2, ts3); 
} 
// or generically 
public static <T> boolean equalsExceptForNulls(T[]... tss) { 
    for(int i = 0; i < tss.length - 1; i++) 
     for(int j = i + 1; i < tss.length; j++) 
      if(!equalsExceptForNulls(tss[i], tss[j]) 
       return false; 
    return true; 
} 

你的問題是,ARRAY3正被用於確定要比較哪些行。

在第一個測試中,您要比較第1,2,3行,第二個測試是比較第0行和第3行。第一個測試應該是false,第二個測試應該是true。

我在調試器中逐句通過您的代碼,發現問題。我建議你這樣做。

我也將使用的int[]代替Integer[]

+0

在第一個測試中,我將比較{1,2,3},{1,0,3}和{1 ,2,3}。第二個:{1,0,3},{0,0,3},{0,3,3}。第二行的問題是{0,0,3}和{0,3,3}的處理方式爲{0,3}。我不知道如何修改代碼以區分{0,0,3}和{0,3,3}(我仍然應該使用HashMap)。 – 2012-01-10 09:54:53

+0

但是,您沒有比較三個數組,您只比較前兩個數組,第三個數組用於確定要比較的行。我不明白你爲什麼使用'Row'或'HashMap'。我只能承擔它的功課,所以我不知道如何改變你的代碼而不用重寫它。 – 2012-01-10 10:01:39

+0

你必須清楚地定義你正在做的事情,並確保你的代碼在調試器中這樣做。你應該試着在你的代碼中清楚你想要達到的目標以及你爲什麼做出選擇。 – 2012-01-10 10:04:04

1

我不太清楚你想什麼來完成,但會不會是你的問題出在方法

public boolean equals(Object obj) { 
     if(this == obj) 
      return true; 
     if((obj == null) || (obj.getClass() != this.getClass())) 
      return false; 
     // object must be Row at this point 
     Row row = (Row)obj; 
      return (value == row.value); 
    } 

因爲

if(this == obj) 

比如你想有一個值比較 - 但是您使用「==」comperator得到的是兩個對象引用的比較?

所以也許

if(this.equals(obj)) 

是你想要的嗎?

此外,你有沒有嘗試在每條語句的調試模式語句中遍歷代碼?我猜doiing這樣可以快速找到你的錯......

歡呼:)

+0

'if(this.equals(obj))'是這個方法試圖實現的。如果你調用它,它會進入無限遞歸。 – 2012-01-10 09:40:36

+0

是的,我做了剔除,並且我發現HashMap不允許保留類似的條目,例如它將保留{0,3},而不是{0,0,3}和{0,3,3}。所以,這些行變得相似,儘管它們是不同的。我被這個代碼困住了...我只需要在多個二維數組中找到真正相似的行。而已。 – 2012-01-10 09:43:18

+0

噢,你是對的!我沒有注意到他正在重寫equals方法..嗯,這是一個嘗試:) – 2012-01-10 09:44:32

1

有你的方法的一個基本問題,這導致了這個bug。您正在使用地圖來確定其他行中元素的位置。如果在行中存在重複元素的情況下構建映射,則它們的先前索引將被過分轉換。這正是你的情況。第二個數組的第二行有一個重複的零點。

這裏是地圖是什麼樣子第二行

map1 = ((Row(1), 0), (Row(0), 1), (Row(3), 3)) 
map2 = ((Row(0), 1), (Row(3), 3)) 

Nnotice只有兩個在MAP2元素bcoz第一個與第二個overwitten。當你從第三個數組中查找第二行的元素時,查找總是成功的(因爲它只查找0和3而不查找1)

此外,檢查失敗的條件是不完整即

if (result1 == null || result2 == null) { 
    return false; 
} 

應該

if (result1 == null || result2 == null || !result1.equals(i) || !result2.equals(i)) { 
    return false; 
} 

在我看來,你不應該使用的地圖都沒有。而是逐個比較每個元素。爲了推廣不同長度數組的代碼,可以嘗試使用ArrayList類的size()方法。

如果您對使用地圖很重要,那麼您應該使用每個數組元素的索引作爲鍵,將Row對象作爲值使用,而不是相反。