2016-07-18 4 views
1

ファイルの解析に関する質問があります。あなたは約30すべての行に異なる文字列を持っているラインのあるスイッチケースvs. If、複数の文字列を比較する場合else

while(scan.hasNextLine()){ 
    line = scan.nextLine();//this gets the whole line 
    if(line.contains("SomeDataIKnow"){ 
     data = new Scanner(line).useDelimiter("=");//scans just the one line 
     value = data.next();//sets value to the string right after the = 
     this.Data1 = value; 
    } 
    else if(line.contains("DifferentDataIKnow"){ 
     data = new Scanner(line).useDelimiter("="); 
     value = data.next(); 
     this.Data2 = value; 
} 

マインドは、ステートメントが含まれています。ここに私はファイルを解析そのように文の数が見えるものです。

各「=」の前の言葉は、等号の後には言いますが、後には言いません。だから私は特定のデータを探して、等号の後にそれらの値を取得して解析する必要があります。私は通常、2つまたは3つ以上のステートメントがある場合、ifステートメントを使用すべきではないことを知っています。誰かがそれを行う別の方法のアイデアを持っている場合、私は興味がありますか?おそらく私は思っていたが、30行で助けてくれるかどうかは分からないかもしれない。また、ファイルを視覚化するのに役立つ場合は、合計400本のラインがありますが、そのうち約30本が必要です。私が知っているchanges.THE DATAがだから私は

をNEED値を=という他の情報の

Device.Aバンチ:私は、ファイル内のファイルが、フルラインの例のようなものになるだろう投稿することはできません私は複数のファイルを解析し、データは変更されないDATA I KNOW部分を除いて変更され、必要な値を持つ行を見つけるために使用されます。申し訳ありませんが、これはすべて混乱するように思えます。

+0

'contains'(または' startsWith'、 'endsWith'など)を使用しているときにswitch文を使用することはできません。スイッチは等価でのみ一致します。 –

+2

すべての*有効な* **接頭辞**を配列に入れて反復することができます。 –

+0

文字列を分割するために 'Scanner'を作成する必要はありません。他のアプローチの中でも' line.split( "=") 'を使うことができます。 –

答えて

0

マップを使用することも可能です。各行をスキャンするときに、キーが '='の前に知っている部分で、値が '='の後の部分であるエントリをマップに追加してください。

そして、ループの後に、以下のように:

this.Data1 = map.get("SomeDataIKnow"); 
this.Data2 = map.get("DifferentDataIKnow"); 

など

2

あなたがこの方法をコーディングしてはならない、DRYは、コーディングの中で最も重要なルールです - あなたはあなたのswitch文を見たとき、あなたは多くの冗長性があります。 if/elseifチェーンをこのように使用しない理由は、switch文にも当てはまります。スイッチコードは冗長なコードになるため、悪いコードになります。

最初に行うべきことは、各ブロックで何が違うかを見ることです。ここにあなたの冗長コードは次のとおりです。

if(line.contains("SomeDataIKnow"){ 
    data = new Scanner(line).useDelimiter("=");//scans just the one line 
    value = data.next();//sets value to the string right after the = 
    this.Data1 = value; 
} 
else if(line.contains("DifferentDataIKnow"){ 
    data = new Scanner(line).useDelimiter("="); 
    value = data.next(); 
    this.Data2 = value; 
} 

違いは[SomeDataIKnow、データ1]対[DifferentDataIKnow、データ2]

スカラは、このようなデータを格納するための良い方法ではありませんされている - 彼らは多くの場合、あなたはコードを作成します明らかに簡単な方法がないので上記のように、一般的に私はマップを使用します。これは、いくつかの問題を持っていますが、作品

String[] strings=new String[]{"SomeDataIKnow","DifferentDataIKnow"}; 
Map results=new HashMap<String, String>() 

for(String sub:strings) 
{ 
    if(line.contains(sub){ 
     data = new Scanner(line).useDelimiter("="); 
     value = data.next(); 
     results.put(sub, value); 
} 

:私は私のコードベースでこのコードを見たら

だから私の最初のリファクタリングは次のようになります。チェックする新しい文字列があるときにコードを追加する必要はありません。コードは30x減らされ、ifステートメント/コードへのパッチは30の異なる場所で繰り返す必要はありません。

最大の問題は、もはや値を調べることは自明ではないということです。あなたは文字列 "SomeDataIKnow"、尻の痛みの鍵が必要です...あなたは変数 "Data1"を持っていました。

あなたは「データ1」を保持したい場合は、のようなあなたの文字列何かを作ることができます。

String[] strings=new String[]{"SomeDataIKnow:Data1","DifferentDataIKnow:Data2"}; 

をしてから= sub.split String []型分割(「:」)を行うと分割により検索を行います[1]

この後、this.Data1を使用する代わりに、合理的なresults.get( "Data1")を使用します。

このような一般的な操作にメタデータを提供する方法はたくさんあります。DRYを維持している限り、ほとんどの場合うまく動作します。私は文字列配列の構造体を使用するのは、初期化して作業するのが簡単だからです... splitの場合も同じです。別のアプローチの例として

、あなたは本当にあなたがこのようなあなたのクラスを設定することができスカラを使用したい場合:

class MyClass{ 
    @SearchStr("SomeDataIKnow") 
    String Data1; 
    @SearchStr("DifferentDataIKnow") 
    String Data2; 
... 

注釈は、これらの日に処理するのは簡単です - あなたは、単にすべてを行くだろうクラス内の@SearchStrアノテーションを使用して検索用語を作成し、上記と同じ方法でループし、結果の値を対応する変数に埋め込みます。

このようなリファクタリングパターンのトリックは、単純に違いを特定してグループ化することです。あなたが快適に感じるようにしたり、あまり複雑さを増やさないようにする方法です。

ちなみに、マップ内の結果は、使用された場所を参照してください。リファクタリングすることができる他の冗長コードがあることがよくあります。このようなリファクタリングは、コードベース全体で大幅な節約をすることができます。

0

Regex Patternを使用することをおすすめします。ファイルが大きすぎない場合は、ファイル全体をメモリに読み込んで、慎重に作成された正規表現パターンを使用して(SomeDataIKnow|DifferentDataIKnow|...)=を検索し、等号の前の一致するテキストと、=と次の改行の間のすべてのテキストを取得します。

この主な効果は、プログラムが40回ではなく1回だけファイルの内容をスキャンできるようにすることです。内容を調べることで、物事がゆっくり進む原因になっている場合は、それが助けになるはずです。

あなたは等号の前にマッチしてしまった正確なパターンを知ったら、あなたはあなたがswitch文の中で使用したり、HashMap<>やビルK.によって提案された他のアプローチのいずれかで調べることができ、特定の文字列を持っている

関連する問題