2016-10-07 4 views
1

ウェブサイトから不要な画像を削除しようとしています。製品画像フォルダには200000以上の画像が含まれています。私は、リスト内で非アクティブな製品コードのリストを持っています。別のリストにファイル名のリストがあります。ここでC#リストと他のリストとを比較する

List<string> lFileList = files.ToList(); 
List<string> lNotinfiles = new List<string>(); 
foreach (var s in lFileList) 
{ 
    var s2 = (from s3 in lProductsList 
      where s.Contains(s3.cProductCode) 
      select s3.cProductCode).FirstOrDefault(); 
    if (s2 == null) 
    { 
     lNotinfiles.Add(s); 
    } 
} 

lProductsListが使用されていないProductCodesを含むリストです。 イメージリストには同じ製品の複数のイメージが含まれていますが、イメージ名には製品コードが含まれています(ほとんどの場合、_1、_2.jpgがあります)

上記のコードは機能しますが、リストにないを取得するための単一のフォルダ分間。私は、次を試しましたが、それは15分以上を要した。

var s2 = (from s3 in lProductsList 
      where s.IndexOf(s3.cProductCode) >= 0 
      select s3.cProductCode).FirstOrDefault(); 

また、私は動作しませんでしたそのすべて一緒にループを削除しようとしています。

これをより速く達成するための最良の方法は何ですか。

答えて

2

私にはお勧めします:を使用し、ToList、おそらくGroupByでお待ちください。 ToList

HashSet +使用は現在、あなたのコードはO(n)の2の時間複雑である - あなたは、外側のリストを反復処理し、各項目の内側のリストのすべての項目を繰り返します。

lProductsListの種類をリストから、コードを含むHashSet<string>に変更します。 HashSetの項目を見つけることはo(1)です(リストはo(n)です)。次に、lFileListの各時刻を繰り返して、それらがlProductsListにあるかどうかを調べると、o(n)2ではなくo(n)の時間複雑さになります。

var notInUseItems = new HashSet(from item in lProductsList 
           select item.cProductCode); 

//Notice that here I am not using the materialized `lFileList` 
lNotinfiles = files.Where(item => !notInUseItems.Contains(item)); 
:あなたのコードのコンテキストでそれを置くことについては

var items = (new[] { "1", "2", "3","4","5","6","7","8","9","10" }).SelectMany(x => Enumerable.Repeat(x, 10000)).ToList(); 
var itemsToFilterOut = new List<string> { "1", "2", "3" }; 

var efficientItemsToFilterOut = new HashSet<string>(itemsToFilterOut); 

var watch = System.Diagnostics.Stopwatch.StartNew(); 
var unwantedItems = items.Where(item => itemsToFilterOut.Contains(item)).ToList(); 
watch.Stop(); 
Console.WriteLine(watch.TotalMilliseconds); 

watch = Stopwatch.StartNew(); 
var efficientUnwantedItems = items.Where(item => efficientItemsToFilterOut.Contains(item)).ToList(); 
watch.Stop(); 
Console.WriteLine(watch.TotalMilliseconds); 

このコードはあなたに2つのリストを使用した場合、またはリストとのHashSetを使用した場合の時間差を表示します


GROUPBY

さらに - あなたは、リストには複数のアイテムが同じキーにマッピングされていると言いました。フィルタリングする前にGroupByを使用してください。このほかの性能を確認してください:

watch = Stopwatch.StartNew(); 
var moreEfficientUnwantedItems = items.GroupBy(item => item) 
    .Where(group => efficientItemsToFilterOut.Contains(group.Key)) 
    .Select(group => group.Key); 
watch.Stop(); 
Console.WriteLine(watch.TotalMilliseconds); 

をどのように重要な重複の量、それとあれば必要な使用あなたがリストにあなたの(私は仮定)の配列を変換してやるさGroupBy

+1

watch.Elapsed.TotalMillisecondsこの中でelapsedMillisecondsにアクセスするには、はるかに優れた性質であります原因は、TotalMillisecondsが2倍で、ElapsedMillisecondsが長いためですdは丸められます。 – Botonomous

+0

問題はありません。ElapsedTicksもlongまたはint64なので、同じ運命に陥ります。 – Botonomous

+0

コードを測定するときに.selectの後に.ToList()を必ず付けてください:)遅れて実行すると、あなたのスニペットに表示されます。 – Botonomous

0

を分析するために、あなたのデータをチェックa foreach forを直接アレイに使用すると、少なくとも少し速くなります。

List<string> lNotinfiles = new List<string>(); 
      for(int i = 0; i < files.Count(); i++) 
      foreach (var s in files) 
      { 
       var s2 = (from s3 in lProductsList where s.Contains(s3.cProductCode) select s3.cProductCode).FirstOrDefault(); 
       if (s2 == null) 
        { 
         lNotinfiles.Add(s); 
        } 
      } 
1

つの提案:

  1. 代わりO(N)のより良いcompexity O(1)を持っているHashSet<String>としてNotInFilesを整理するすべてののファイルが
  2. を取得しているまで待つことはありませんファイル.ToList()すなわちを実体ないください。このよう

何か:

//TODO: you have to implement this 
    prtivate static String ExtractProductCode(string fileName) { 
    int p = fileName.IndexOf('_'); 

    if (p >= 0) 
     return fileName.SubString(0, p); 
    else 
     return fileName; 
    } 

...

HashSet<String> NotInFiles = new HashSet<String>(
    lNotinfiles, 
    StringComparer.OrdinalIgnoreCase); // file names are case insensitive 

..

var files = Directory 
    .EnumerateFiles(@"C:\MyPictures", "*.jpeg", SearchOption.AllDirectories) 
    .Where(path => Path.GetFileNameWithoutExtension(path)) 
    .Select(path => ExtractProductCode(path)) 
    .Where(code => !NotInFiles.Contains(code)) 
    .ToList(); // if you want List materialization 
関連する問題