2016-07-26 54 views
0

我正在尋找一種方式來讀取未知維度(不是長度)的數組中的一系列元素。閱讀數組中值的範圍與未知尺寸

客戶端可以發送對象的讀取請求並指定要讀取的範圍。例如,輸入字符串可以是這樣的:「1:2:3:2,2:3:1:4」。這意味着他想要讀取數組[1] [2] [3] [2]到[2] [3] [1] [4]中的元素。

讀書,我創造了這個功能的混凝土構件:

public Object readValue(Object obj,int[] positions) { 
    Object value = null; //Result 
    int objDimension = getDimension(obj); //Dimesion of the array 
    System.out.println("Dimension: " + objDimension); 
    try { 
     Object[] aux = (Object[]) obj; 
     for (int i = 0; i < objDimension - 1; i++) { 
      int pos = positions[i]; 
      aux = (Object[]) aux[pos]; 
     } 
     value = aux[positions[objDimension - 1]]; 
     System.out.println("Result: " + value); 
    } catch (ArrayIndexOutOfBoundsException e) { 
     // TODO: Send a fault to the client. 
     System.out.println("Error: "+e.getMessage()); 
    } 
    return value; 
} 

public static int getDimension(Object value) { 
    Class<?> clazz = value.getClass(); 
    String className = clazz.getName(); 
    int dimension = 0; 
    for (int i = 0; i < className.length(); i++) { 
     if (className.charAt(i) != '[') { 
      dimension = i; 
      break; 
     } 
    } 
    return dimension; 
} 


//Example. 
public static void main(String[] args) { 
    // TODO code application logic here 
    TestMultiDimensioNRead test = new TestMultiDimensioNRead(); 
    Integer[][][][] testSubject = new Integer[5][2][4][]; 

    testSubject[0][0][2] = new Integer[8]; 
    testSubject[0][0][0] = new Integer[15]; 
    testSubject[0][0][1] = new Integer[20]; 
    testSubject[0][0][3] = new Integer[2]; 
    testSubject[1][1][2] = new Integer[7]; 
    testSubject[1][1][2][0] = 80; 
    test.readValue(testSubject,new int[]{1, 1, 2, 0}); 
} 

我在想一個好辦法可以計算每個維度的長度之間的differens。

如果任何人都可以有一個好主意,我真的很感激。

在此先感謝。

編輯1:在這個問題中發佈的代碼的確讀取了未知維數組中給定位置的值。我的問題是讀取介於給定點之間的所有元素。這在最初的問題中可能不太清楚。

+1

這可能不是建議的方法,原因很多。我能問你想要完成什麼嗎?我可能會重新考慮你在解決問題的方式。 – Kurtymckurt

+0

對於服務器來說,其中一項服務是從任何維數的數組中讀取一系列值。數組沒有預定義,並且沒有角度限制(我寫了255,因爲來自Java的維度上限)。這是在服務器啓動時創建的,並來自配置文件。順便說一下,歡迎任何替代方式或想法,謝謝。 – gabun88

+0

您可以將數據中的維數作爲參數傳入嗎?如果調用代碼知道它(至少對於這種用法),編寫一個算法來解決這個問題毫無意義。 – Kurtymckurt

回答

0

找到了解決問題的方法,也許這對某人來說是有幫助的。 我沒有包含任何檢查,這是更多的測試用例,看看是否有用。

public class TestReadMultiDimensionArray { 

private int[] startPosition;    //Start position. 
private int[] endPosition;     //End position. 
private boolean inRange = false;   //If the current position is in range. 
private List<Object> result;    //List to store the values we find. 

public TestReadMultiDimensionArray() { 
    result = new ArrayList<>(); 
} 

public static void main(String[] args) { 
    TestReadMultiDimensionArray test = new TestReadMultiDimensionArray(); 
    Integer[][][][] testSubject = new Integer[2][2][4][]; 
    //(0,0,y,z) 
    testSubject[0][0][0] = new Integer[]{1};         //(0,0,0,0) 
    testSubject[0][0][1] = new Integer[]{2};         //(0,0,1,0) 
    testSubject[0][0][2] = new Integer[]{3};         //(0,0,2,0) 
    testSubject[0][0][3] = new Integer[]{4};         //(0,0,3,0) 
    //(0,1,y,z) 
    testSubject[0][1][0] = new Integer[]{5};         //(0,1,0,0) 
    testSubject[0][1][1] = new Integer[]{6};         //(0,1,1,0) 
    testSubject[0][1][2] = new Integer[]{7, 8, 9};        //(0,1,2,0) (0,1,2,1) (0,1,2,2) 
    testSubject[0][1][3] = new Integer[]{10};         //(0,1,3,0) 
    //(1,0,y,z) 
    testSubject[1][0][0] = new Integer[]{11, 12};        //(1,0,0,0).. 
    testSubject[1][0][1] = new Integer[]{13, 14, 15}; 
    testSubject[1][0][2] = new Integer[]{16, 17, 18}; 
    testSubject[1][0][3] = new Integer[]{19, 20, 21};       //..(1,0,3,2) 
    //(1,1,y,z) 
    testSubject[1][1][0] = new Integer[]{22, 23};        //(1,1,0,0).. 
    testSubject[1][1][1] = new Integer[]{24, 25, 26}; 
    testSubject[1][1][2] = new Integer[]{27, 28, 29, 30, 31, 32, 33, 34}; 
    testSubject[1][1][3] = new Integer[]{35, 36};        //..(1,1,3,1) 
    //Launch the test. 
    test.readValue(testSubject); 
} 

/** 
* 
* @param obj The Array from where we want to get the data. 
*/ 
public void readValue(Object obj) { 
    //Where should it start. 
    startPosition = new int[]{0, 1, 0, 0}; 
    //Where should it stop. 
    endPosition = new int[]{1, 1, 1, 2}; 
    System.out.println("Start Position:" + Arrays.toString(startPosition) + " End Position:" + Arrays.toString(endPosition)); 
    int[] currentPosition = new int[]{-1, -1, -1, -1}; 

    //Call to the method. 
    testRead((Object[]) obj, 0, currentPosition); 
    //Result to array. 
    Object[] arrayToReturn = result.toArray(new Object[0]); 
    System.out.println("Result: " + Arrays.toString(arrayToReturn)); 
} 

/** 
* Recursive method that looks for the values in a multi-dimensional array, in a given range. /!\ No checks are implemented here, wrong input can end in a 
* StackOverFlow. 
* 
* @param obj The array in Object[] form. 
* @param currentDimension The dimension we are currently in. 
* @param result The reference to the list that will store all the values we found. 
* @param currentPosition The current position we are in. 
*/ 
private void testRead(Object[] obj, int currentDimension, int[] currentPosition) { 
    for (int i = 0; i < obj.length; i++) { 
     currentPosition[currentDimension] = i; 
     if (Arrays.equals(startPosition, currentPosition) && currentDimension == (currentPosition.length - 1)) { 
      //Found the start position. 
      System.out.println("############ START ############"); 
      inRange = true; 
     } 

     if ((i >= startPosition[currentDimension] && i <= endPosition[currentDimension]) || inRange == true) { 
      //We are in the write track to get to the values we are looking for. 
      if (obj[i] instanceof Object[]) { 
       //The data contained in the cell is an array. 
       testRead((Object[]) obj[i], currentDimension + 1, currentPosition); 
      } else { 
       //The data contained in the cell is a scalar. This is what we where looking for. 
       System.out.println(Arrays.toString(currentPosition) + " Data: " + obj[i]); 
       result.add(obj[i]); 
      } 
     } 

     if (Arrays.equals(endPosition, currentPosition) && currentDimension == (currentPosition.length - 1)) { 
      //Found the end position. 
      System.out.println("############ END ############"); 
      inRange = false; 
     } 
    } 
} 

} 

任何問題或想法,以更好的代碼是值得歡迎的。

1

你可以使用一個遞歸解決方案:

public class Test { 
    private class TestMultiDimensioNRead { 
     public Integer readValue(Object testSubject, int[] coordinates) { 
      return readValue(testSubject, coordinates, 0); 
     } 

     private Integer readValue(Object testSubject, int[] coordinates, int which) { 
      if (testSubject instanceof Object[]) { 
       Object[] subject = (Object[]) testSubject; 
       if (coordinates.length > which + 1) { 
        return readValue(subject[coordinates[which]], coordinates, which + 1); 
       } else { 
        return (Integer) subject[coordinates[which]]; 
       } 
      } else { 
       // Throw some sort of exception? 
       return -1; 
      } 
     } 

     public Iterator<Integer> readValues(Object testSubject, int[] coordinates, int count) { 
      return readValues(testSubject, coordinates, count, 0); 
     } 

     private Iterator<Integer> readValues(Object testSubject, int[] coordinates, int count, int level) { 
      if (testSubject instanceof Object[]) { 
       Object[] subject = (Object[]) testSubject; 
       if (coordinates.length > level + 1) { 
        return readValues(subject[coordinates[level]], coordinates, count, level + 1); 
       } else { 
        return new Iterator<Integer>() { 
         int i = 0; 
         Integer[] intSubject = (Integer[]) subject; 

         @Override 
         public boolean hasNext() { 
          return i <= count; 
         } 

         @Override 
         public Integer next() { 
          return intSubject[coordinates[level] + (i++)]; 
         } 
        }; 
       } 
      } else { 
       // Throw some sort of exception? 
       return null; 
      } 
     } 

    } 

    public void test() { 
     TestMultiDimensioNRead test = new TestMultiDimensioNRead(); 
     Integer[][][][] testSubject = new Integer[5][2][4][]; 

     testSubject[0][0][2] = new Integer[8]; 
     testSubject[0][0][0] = new Integer[15]; 
     testSubject[0][0][1] = new Integer[20]; 
     testSubject[0][0][3] = new Integer[2]; 
     testSubject[1][1][2] = new Integer[7]; 
     testSubject[1][1][2][0] = 80; 
     testSubject[1][1][2][1] = 79; 
     testSubject[1][1][2][2] = 78; 
     Iterator<Integer> them = test.readValues(testSubject, new int[]{1, 1, 2, 0}, 3); 
     for (Integer x = them.next(); them.hasNext(); x = them.next()) { 
      System.out.println(x); 
     } 
     System.out.println(); 

    } 

    public static void main(String args[]) { 
     try { 
      new Test().test(); 
     } catch (Throwable t) { 
      t.printStackTrace(System.err); 
     } 
    } 
} 

打印80預期。

在理智檢查方面可能還有更多的工作要做,但這似乎有效。

+0

我明白你的意思,但真正的問題是要讀取範圍。我的意思是範圍可以是這樣的:從元素[0] [0] [0] [0]到[4] [1] [1] [0]讀取。這意味着你必須閱讀這兩者之間的所有元素。結果將是一個包含該範圍內所有值的數組。一個簡單的例子可以是:從[0] [0] [0] [0]到[0] [0] [0] [5]讀取,這將是[0] [0] [0] [0], [0] [0] [0] [1],[0] [0] [0] [2],[0] [0] [0] [3],[0] [0] [0] [4 ]和[0] [0] [0] [5]。 – gabun88

+0

@ gabun88 - 你也許可以通過在我們找到正確位置的級別返回一個倉促構造的'Iterator'來做到這一點,但只有當範圍處於最深層時纔可以。例如,執行諸如'[0] [0] [0] [0]至[0] [0] [5] [5]'的操作將很困難。 – OldCurmudgeon

+0

@ gabun88 - 我添加了一個'readValues',它返回一個'Iterator' - 希望有幫助。 – OldCurmudgeon