2010-12-07 8 views
4

私は2つのフォルダAとBを持っています。複数のファイルがあり、Bの中に複数のファイルがあります。私はBのファイルと同じファイル以外のファイルをチェックする必要があります...全体の検索結果を与える...名前に基づいて同一でないファイルに対して2つのフォルダを比較するにはどうすればよいですか?

var filesnotinboth = from f1 in dir1.GetFiles("*", SearchOption.AllDirectories) 
        from f2 in dir2.GetFiles("*",SearchOption.AllDirectories) 
        where f1.Name != f2.Name 
        select f1.Name; 

何か提案がありますか?

答えて

9

このアプローチは非常に非効率的です。新しいf1で開始するたびにdir2.GetFilesと呼ぶ予定です。 f2の現在のf1と一致しない場合は、一致するようにします。たとえそれがの後にf1と一致しても、出力されます。そのDIR1は、A、BおよびCが含まれており、DIR2は、CおよびDが含まれています。このように終わるだろうと想像:だから、結果はA、A、B、B、Cになり

f1 f2 Result of where? 
A  C True 
A  D True 
B  C True 
B  D True 
C  C False 
C  D True 

- あなたがしたいですまだは(あなたが望んしなかった) Cを持っている - だけでなく、かなりのように、多くの場合、AとB

としてあなたはこのように、集合演算を使用したい:今すぐ

var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories) 
        .Select(x => x.Name); 

var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories) 
        .Select(x => x.Name); 

var onlyIn1 = dir1Files.Except(dir2Files); 

そのべき仕事、そしてより効率的に...

編集:以前のバージョンの質問に基づいて、AのファイルがBのファイルではないとします。 (私はそれが最初の5分に編集されたかどうかわからないんだけど、明らかに現在のコードはBではなくAに何かを返すために行くのではありません)あなたは、対称差をつけたい場合は

HashSet<T>.SymmetricExceptWithを使用します。

var inExactlyOneDirectory = new HashSet<string>(dir1Files); 
inExactlyOneDirectory.SymmetricExceptWith(dir2Files); 

SymmetricExceptWithは、新しいセットまたはシーケンスだけを返す代わりに、既存のセットを変更するvoidメソッドであるという点を嫌います。他のものとは別に、変数名は最初のものではなく2番目のステートメント)

EDIT:名前とサイズによって一意性が必要な場合は、r両方を表す匿名型が必要です。残念ながら、それに基づいてHashSet<T>を作成するのは難しいです。ですから、このような拡張メソッドをお勧めします:

public static HashSet<T> ToHashSet<T>(this IEnumerable<T> set) 
{ 
    return new HashSet<T>(set); 
} 

その後:あなたの現在のソリューションが動作しませんなぜ

var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories) 
        .Select(x => new { x.Name, x.Length }); 

var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories) 
        .Select(x => new { x.Name, x.Length }); 

var difference = dir1Files.ToHashSet(); 
difference.SymmetricExceptWith(dir2Files); 
+0

@Jon Skeet:OPは、dir1またはdir2にありますが、*両方ではないファイルが必要です。 – Ani

+0

@Ani:元のコードに基づいて完全にはっきりしているわけではありません。この質問はもともと対称的な違いではなく「AではあるがBではない」ことを示唆していたと思います。しかし、対称的な違いも含めて答えを編集しました。 –

+0

@ bala3569:あなたが何を意味するのか分かりませんが、答えには両方の解決策を提供しました。 –

-1
var files2 = dir2.GetFiles("*", SearchOption.AllDirectories); 
var filesnotinboth = dir1.GetFiles("*", SearchOption.AllDirectories) 
         .Where(f1 => !files2.Any(f2 => f2.Name == f1.Name)); 
+0

'dir2 'の下にあるすべてのファイルを何度も取り出したいのですが? –

+0

@jon:そうだよ、私が思っている間に書いていただけだよ。 – PierrOz

+0

'filesnotinboth'?私はそれがあなたの質問が返す質問ではないと思います –

2

ジョンスキートの答えは理解のお手伝いをする必要があり、基本的にあり非効率的な。

この問題を解決する方法の1つは、現在のHashSet(Of T)オブジェクトを、そのオブジェクトまたは指定されたコレクションのいずれかに存在する要素のみを含むように変更するHashSet.SymmetricExceptWithメソッドを使用することですどちらも。"

// Thanks to Jon Skeet for template 
var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories) 
        .Select(x => x.Name); 

var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories) 
        .Select(x => x.Name); 

var filesNotInBoth = new HashSet<string>(dir1Files); 

filesNotInBoth.SymmetricExceptWith(dir2Files); 
関連する問題