ホームページ  >  記事  >  Java  >  Java で関数を使用して 2 次元配列を走査するにはどうすればよいですか?

Java で関数を使用して 2 次元配列を走査するにはどうすればよいですか?

WBOY
WBOY転載
2023-05-07 19:34:061178ブラウズ

序文

配列トラバーサルについては、基本的にすべての開発者がそれについて書いています。トラバーサル自体については特に言うことはありませんが、トラバーサル プロセス中に複雑なビジネス ロジックがある場合、次のことがわかります。コードのレベルは徐々に深くなります。

たとえば、単純なケースでは、2 次元配列から偶数を見つけてリストに保存します。

2 次元を横断します。配列して各要素を判定する 偶数かどうかを簡単に書くことができます。 例えば:

public void getEven() {
    int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}};
    List<Integer> ans = new ArrayList<>();
    for (int i = 0; i < cells.length; i ++) {
        for (int j = 0; j < cells[0].length; j++) {
            if ((cells[i][j] & 1) == 0) {
                ans.add(cells[i][j]);
            }
        }
    }
    System.out.println(ans);
}

上記の実装でも問題ありませんが、このコードの深さは簡単に記述できます。 3レベル; 上記の場合 if 他に判定条件があれば簡単にコードレベルを上げることができる; 2次元配列でも良いが、3次元配列だと1回の走査が3レベルになる; ちょっとした工夫で論理的には、4 つまたは 5 つのレベルは数分で達成できますよね?

それでは、問題は、コード レベルが上がるとどのような問題が発生するかということです。

コードが実行できる限り、問題は何でしょうか? !

1. 関数メソッドによってコード レベルが削減される

多次元配列の走査レベルは当然ながら非常に深いため、それを削減する方法はあるのでしょうか?

この問題を解決するには、要点を押さえることが重要ですが、横断の要点は何でしょうか?各要素の座標を取得しましょう!では、何ができるでしょうか?

関数メソッドを定義し、入力は関数座標であり、この関数本体でトラバーサル ロジックを実行します。

上記の考えに基づいて、簡単にできると思います。 2 次元配列トラバーサルの一般的なメソッドを書くのは簡単です

public static void scan(int maxX, int maxY, BiConsumer<Integer, Integer> consumer) {
    for (int i = 0; i < maxX; i++) {
        for (int j = 0; j < maxY; j++) {
            consumer.accept(i, j);
        }
    }
}

主な実装は上記です。関数メソッドはデフォルトで JDK が提供する BiConsumer を直接使用します。渡される 2 つのパラメータは、次のように両方とも int 配列です。下の表; 戻り値なし

それでは、上記をどのように使用するのでしょうか?

上記の例と同じですが、変更後は次のようになります:

public void getEven() {
    int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}};
    List<Integer> ans = new ArrayList<>();
    scan(cells.length, cells[0].length, (i, j) -> {
        if ((cells[i][j] & 1) == 0) {
            ans.add(cells[i][j]);
        }
    });
    System.out.println(ans);
}

前と比べると、レイヤーが 1 つだけ減っているように見えますが、

ただし、配列が 3 次元、4 次元、または無次元になっても、この変更の書き込みレベルは変わりません。

2。トラバーサル中のリターンサポート

Previous 通常のトラバーサル実装では問題ないのですが、トラバーサル処理中に何らかの条件が発生して直接リターンした場合、サポートできるのでしょうか?

たとえば、2 次元配列を走査していて、その中に偶数が含まれているかどうかを判断したい場合、どうすれば四捨五入できるでしょうか?

リターンをサポートできるように、スキャン メソッドについて慎重に考えてください。主な問題は、関数メソッドの実行後、ループを続行するか直接リターンするかをどうやって判断すればよいかということです。

それは簡単です。思い浮かぶのは、実行ロジックに追加の戻り値を追加して、ループを中断して直接戻るかどうかをマークすることです。

このアイデアに基づいて、簡単なデモ バージョンを実装できます

定義ループの添字戻り値を受け入れる function メソッド

@FunctionalInterface
public interface ScanProcess<T> {
    ImmutablePair<Boolean, T> accept(int i, int j);
}

一般的なループ メソッドは、それに応じて変更できます。

public static <T> T scanReturn(int x, int y, ScanProcess<T> func) {
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            ImmutablePair<Boolean, T> ans = func.accept(i, j);
            if (ans != null && ans.left) {
                return ans.right;
            }
        }
    }
    return null;
}

上記の考えに基づいて、私たちの実際の使用姿勢は次のとおりです:

@Test
public void getEven() {
    int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}};
    List<Integer> ans = new ArrayList<>();
    scanReturn(cells.length, cells[0].length, (i, j) -> {
        if ((cells[i][j] & 1) == 0) {
            return ImmutablePair.of(true, i + "_" + j);
        }
        return ImmutablePair.of(false, null);
    });
    System.out.println(ans);
}

上記の実装は私たちのニーズを満たすことができます。唯一厄介なのはリターンです。これは常に少しエレガントではありません。このメソッドの他に、他のメソッドもあります。方法?

戻り値について考えたので、パラメーターを渡す場合はどうすればよいでしょうか?定義されたパラメータを使用して、中断して結果を返すかどうかを決定することは可能ですか?

このアイデアに基づいて、最初にパラメーター パッケージング クラスを定義できます。

public static class Ans<T> {
    private T ans;
    private boolean tag = false;

    public Ans<T> setAns(T ans) {
        tag = true;
        this.ans = ans;
        return this;
    }

    public T getAns() {
        return ans;
    }
}

public interface ScanFunc<T> {
    void accept(int i, int j, Ans<T> ans)
}

Ans クラスを通じてループ結果を記録したいと考えています。ここで、tag=true は意味します。ループを続ける必要はありません。ans 結果を直接返すだけです。

対応するメソッド変換と例は次のとおりです。

public static <T> T scanReturn(int x, int y, ScanFunc<T> func) {
    Ans<T> ans = new Ans<>();
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            func.accept(i, j, ans);
            if (ans.tag) {
                return ans.ans;
            }
        }
    }
    return null;
}
public void getEven() {
    int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}};
    String ans = scanReturn(cells.length, cells[0].length, (i, j, a) -> {
        if ((cells[i][j] & 1) == 0) {
            a.setAns(i + "_" + j);
        }
    });
    System.out.println(ans);
}

これは、前のものよりも見栄えが良くなります。 one

実際に実行して、出力が期待と一致するかどうかを確認します。

Java で関数を使用して 2 次元配列を走査するにはどうすればよいですか?##

以上がJava で関数を使用して 2 次元配列を走査するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。