0

ファイルのグループで個別の識別子のコレクションを取得しようとしています。この Lambda クエリの何が間違っていますか:

   var enumDir = Directory.GetFiles(folder);
   var distinctCode = enumDir.Select(s => Path.GetFileName(s).Substring(8, 4))
                              .GroupBy(s => s.ToString());

前もって感謝します ...

編集

@empiの提案。ファイル名から個別の 4 文字の部分文字列のリストを取得することを期待しています。取得したものは何もないか、最初に Path.Get.... の部分をグループに入れ、範囲外のインデックスを取得しました例外。

@Oskar Kjellinの提案では、すべてのファイル名の長さが45文字に設定されていることに言及する必要があります

最終的な解決策 | empi と Oskar に感謝

var enumDir = Directory.GetFiles(folder).Where(a => Path.GetFileName(a).Length > 12);
var distinctCode = enumDir.Select(s => Path.GetFileName(s).Substring(8, 4)).Distinct();

本当に両方の提案の組み合わせです。実際に誰が回答をマークすればよいかわかりません。

4

4 に答える 4

1

例外を回避するために、部分文字列を呼び出す前に常に長さを確認する必要があります...

 enumDir = Directory.GetFiles(folder);
 distinctCode = enumDir.Select(s => Path.GetFileName(s))
.Select( s=> s.Length >= 12 ? s.Substring(8, 4) : s).GroupBy(s => s);

フォルダ内のファイルを実際に制御することはできません。たとえば、Windowsは、画像やその他の一時ファイルのサムネイルのキャッシュであるthumbs.dbを作成できます。

おそらく、固定長のものだけを除外したいでしょう:

 enumDir = Directory.GetFiles(folder);
 distinctCode = enumDir.Select(s => Path.GetFileName(s)).Where(s=>s.Length == 45)
.Select( s=> s.Substring(8, 4)).GroupBy(s => s);
于 2012-04-28T19:20:26.873 に答える
1

enumDir.Select(s => Path.GetFileName(s).Substring(8, 4))-このコードは返されるはずですIEnumerable<string>-このコレクションに問題がないかどうかを確認してください。問題がない場合は、を使用してDistinct()ください。

于 2012-04-28T19:24:21.147 に答える
1

あなたが探しているのは、実際のファイル名を取得することだと思いますが、それらを部分文字列でグループ化します。

var result = Directory.GetFiles(folder)
    .Select(s => Path.GetFileName(s))
    .Where(s => s.Length > 12)
    .GroupBy(s => s.Substring(8, 4));

これで、部分文字列resultであるグループオブジェクトがあり、Keyそれらを列挙すると、そのキーに一致する実際のファイル名が取得されます。

于 2012-04-28T19:34:08.867 に答える
1

正規表現を使用して検証を行うと、これをはるかにうまく行うことができると思います。クエリ内で実行しようとしている種類のチェックは、複雑すぎて 1 つのクエリでは実行できません。そのディレクトリに、予期しないパターンに従っていない他のファイルが存在する可能性があり、すべてが台無しになる可能性があります。その複雑さは、代わりに正規表現で捉えることができます。ファイル名が特定のパターンに従っている場合、単純な正規表現の一致でこれを処理できます。

ファイル名がどのように見えるかわかりませんので、例として Windows Media Center から録画されたテレビを使用します。すべての WMC ファイル名には、特定のパターンがあります。

[title]_[station]_[year]_[month]_[day]_[hour]_[minute]_[second].wtv

次に、すべてのビデオをタイトル別にグループ化するには、次のようにします。

var dir = @"C:\Users\Public\Recorded TV";
var wmcFileRe = new Regex(@"
    ^
    (?<title>.+)
    _
    (?<station>.+)
    _
    (?<date>\d{4}_\d{2}_\d{2})
    _
    (?<time>\d{2}_\d{2}_\d{2})
    \.wtv
    $
", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);
var query =
    from filePath in Directory.EnumerateFiles(dir)
    let fileName = Path.GetFileName(filePath)
    let match = wmcFileRe.Match(fileName)
    where match.Success
    orderby match.Groups["title"].Value,
            match.Groups["date"].Value descending,
            match.Groups["time"].Value descending
    group filePath by match.Groups["title"].Value;

次のような結果が得られます。

例

また、前もって結果の配列を作成しないようDirectory.EnumerateFiles()に代わりに使用Directory.GetFiles()します。その配列は他の場所では必要ありません。

于 2012-04-28T21:33:46.583 に答える