2016-04-04 17 views
0

私は任意にディープネストされた配列を取得し、配列を平坦化し、配列内のヌルオブジェクトを取り除こうとしています。配列を平坦化してnullを取り除く方法は?

たとえば、 [1, 5, [[6, 4], 91, 12, null, [[null]]], -2] のようなネストされた配列を入力して、null値を持たない1次元配列を返すことができるようにします。これをどうやって解決するのだろうか?

私は以下の私の解決策を提供するが、私はjava.lang.Integerのエラーにキャストすることはできません

を得続けます。 最も簡単な(ただし、最速必要)の

public static void main(String[] args) { 
    int[][] numbers = {null, {4, 5, 6},{3, 1, 10}, {4, 2, 9}, null, null}; 
    flatten(numbers); 
} 

public static ArrayList<Integer> flatten(Object[] nestedNumbers) { 
    if (nestedNumbers == null) return null; 
    ArrayList<Integer> flattenedNumbers = new ArrayList<>(); 
    for (Object element : nestedNumbers) { 
     if (element != null) { 
      flattenedNumbers.add((Integer)element); 
     } 
    } 
    return flattenedNumbers; 
} 
+1

** **コンパイルエラーは何ですか? –

+0

より具体的なエラーに編集しました –

+0

配列には2次元しかありませんか? – Tunaki

答えて

6

のJava 8に導入Stream APIを用いて可能な解決策は、以下です。したがって、この方法は、Object[]を受け入れ、少なくとも2つの次元、すなわちint[][]、任意の次元数までの任意のタイプの整数配列を与えることができることを表す。 Objects::nonNull述部を使用して、ヌル要素を除外します。

すると魔法が起こる:Arrays.stream(array)によって返さStream<Object>は、フラットIntStreamにマップされます。その中の要素がObject[]であれば、それは、我々はまだ2つの以上の寸法を有し、そしてこの方法は再帰的に自分自身を呼び出していることを意味し。一方、int[]のインスタンスがある場合、それをそのストリームに置き換えることができます。

例呼び出すコード:

public static void main(String[] args) { 
    int[][][] numbers = {null, {{4}, {5}, {6,1}},{{3,2}, {1}, {10}}, {{4,1}, {2,3}, {9,8}}, null, null}; 
    int[] flat = flatten(numbers); 
    System.out.println(Arrays.toString(flat)); 
} 

もちろん、この方法は、(intnullができないのでフィルタリングすると何も)平坦化する何もない場合であると思われる、int[]を受け付けません。

2

一つの解決策は、該当する可能性があります。

  • あなたの配列を代表する文字列を生成(Arrays.deepToStringはここに参考にすることができ)

    のような
    "[null, [4, 5, 6], [3, 1, 10], [4, 2, 9], null, null]" 
    
  • から削除します。[

    • フィルタへ
    • 反復受信アレイ全体のスペースに,

    • スプリットすべて「ヌル」文字列
    • お好みの数値型にnull以外の文字列を変換して、リストをもたらすために、それを追加します。あなたは浮動小数点数とロケールを分割したい場合には
あなたのソリューションは、(私はあなたはJava 8の使用を許可されていると仮定しています)のようになります。要するに

public static List<Integer> flatten(Object[] nestedNumbers) { 
    String text = Arrays.deepToString(nestedNumbers); 
    System.out.println(text); 
    return Stream.of(text.replaceAll("\\[|\\]|,", "").split("\\s+")) 
     .filter(s->!s.equals("null")) 
     .map(Integer::parseInt) 
     .collect(Collectors.toList()); 
} 

また小数点として,を使用しています1,25あなたが削除する必要がありますどの,を決定する必要がありますと,は、数の一部であり、滞在する必要があります。そのような場合、解決策の後にスペースを持つ,を削除することができます(ただし、そのスペースは、splitに必要なので削除しません)。 replaceAllは正規表現を使用しているので、先読みの(?=...)メカニズムを使用することができます。これにより、現在の試合後の部分をテストすることができます。

したがってreplaceAll("\\[|\\]|,(?=\\s)","")が必要です。削除された,にはスペースが必要ですが、そのスペースは削除されません。

public static int[] flatten(Object[] array) { 
    return Arrays.stream(array) 
       .filter(Objects::nonNull) 
       .flatMapToInt(a -> { 
        if (a instanceof Object[]) return Arrays.stream(flatten((Object[]) a)); 
        return Arrays.stream((int[]) a); 
       }) 
       .toArray(); 
} 

考慮すべき最初のポイントは、int[]Object[]ないということである。

+0

ああ、素敵なハック(そのことを考えていなかった:D) – Tunaki

+0

解決策の主要部分は 'deepToString'によって行われるので、何も再作成する必要はありません:)しかし、文字列を作成するには時間と空間が必要です現実世界のソリューション(あなたはすでに++を持っています)。 – Pshemo

関連する問題