2008-08-29 5 views
4

文字列を文字単位でステップし、それを解析してツリーのような構造を作成する再帰的アルゴリズムを持っています。私は、パーサが現在(エラーメッセージのために)他にある文字インデックスを追跡できるようにしたいが、複数の返される型を扱うタプルのようなものを実装することに熱心ではない。Javaで再帰的アルゴリズムで「完了した」カウントを維持するにはどうすればよいですか?

メソッドの外側で宣言され、再帰メソッドに渡されたInteger型を使用しようとしましたが、最終的なので、再帰呼び出し増分は返されたときに「忘れられています」。 (Integer値の増分により、値渡しのオブジェクト参照点が新しいオブジェクトに渡されるため)

コードを汚染しないような作業を行う方法はありますか?

+0

を確かにない答えが、いくつかの同情を:私は数ヶ月前に似たような状況に遭遇した:-)。私はCommon Lispを使っていたので、単にカウンターの「特別な」(語彙的スコープではなく動的スコープで)宣言することができましたが、他のどの言語でも1行以上のコードが必要です解決する"。 – Ken

答えて

2

すでに擬似可変整数「ハック、」どのようにこのオプションについてを発見したので:あなたは別のParserクラスを作成するため

それは理にかなっていますか?これを行うと、現在の状態をメンバ変数に格納できます。おそらく、スレッドの安全性の問題をどのように処理するのかを考えなければならないでしょうし、この特定のアプリケーションでは過度の作業かもしれませんが、うまくいくかもしれません。

3

これは多分ハックですが、時にはこのようなことをするためにAtomicIntegerを使用しています。これは変更可能です。私はまた、[]サイズ1のint型が渡された例を見てきました

2

私が使用している現在のソリューションは、次のとおりです。その後、

int[] counter = {0}; 

と再帰アルゴリズムに渡し:

public List<Thing> doIt (String aString, int[] counter) { ... } 

と私はそれをインクリメントしたい:

counter[0]++; 

ないスーパーエレガントな、それは動作します...

2

整数は不変です。つまり、引数として渡すと、同じ項目への参照ではなくコピーが作成されます。 (explanation)。

あなたが探している振る舞いを得るには、Integerのみのような独自のクラスを書くことができます。次に、再帰関数に渡します。再帰関数内でインクリメントされます。再帰が終了した後に再度アクセスすると、新しい値が維持されます。

編集:int []配列を使用すると、このメソッドのバリエーションです。Javaでは、配列はプリミティブや不変クラスのようにコピーされるのではなく、参照渡しされます。

0

正直言って、ループを使用する線形アルゴリズムにするために関数をコード化します。非常に大きな文字列を踏んでいる場合、ヒープスペースが足りなくなる可能性はありません。また、カウントを追跡するために余分なパラメータを持つ必要はありません。

これはおそらく、すべての文字に対して関数呼び出しを行う必要がないため、アルゴリズムを高速化した結果になります。

もちろん、再帰的にする必要がある特定の理由がある場合を除きます。

0

1つの可能性は、クラスのメンバー変数にカウントを格納することです。これはもちろん、公開のdoItメソッドが1つのスレッドによってのみ呼び出されることを前提としています。

パブリックメソッドをリファクタリングしてプライベートヘルパーメソッドを呼び出すこともできます。プライベートメソッドは、リストをパラメータとして取り、カウントを返します。たとえば、次のように

public List<Thing> doIt(String aString) { 
    List<Thing> list = new ArrayList<Thing>(); 
    int count = doItHelper(aString, list, 0); 
    // ... 
    return list; 
} 

private int doItHelper(String aString, List<Thing> list, int count) { 
    // ... 
    // do something that updates count 
    count = doItHelper(aString, list, count); 
    // ... 
    return count; 
} 

これはcount変数が実際に呼び出し元に渡されていないので、あなたは、公共のdoIt方法でエラー処理を行うことができますことを前提としています。あなたがそれを行う必要がある場合は、もちろん、例外をスローする可能性:

public List<Thing> doIt(String aString) throws SomeCustomException { 
    List<Thing> list = new ArrayList<Thing>(); 
    int count = doItHelper(aString, list, 0); 
    // ... 
    if (someErrorOccurred) { 
     throw new SomeCustomException("Error occurred at chracter index " + count, count); 
    } 
    return list; 
} 

それはそれはあなたのアルゴリズムが実際にどのように機能するかについての詳細を知らなくても役立つかどうかを知ることは困難です。

1

doItメソッドが呼び出されるたびに増分される静的intクラス変数を使用できます。

1

あなたも行うことができます:

private int recurse (int i) { 

    if (someConditionkeepOnGoing) { 
     i = recurse(i+1); 
    } 

    return i; 
} 
+0

関数内に複数の再帰呼び出しがあり、前の数が1の場合、新しい関数呼び出しはいずれも3を取得する必要があるときに引数2を受け取ります。 – Riptyde4

関連する問題