C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: フルパスからファイル名の一部を使用してのソート


(過去ログ 106 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■63235 / inTopicNo.1)  フルパスからファイル名の一部を使用してのソート
  
□投稿者/ SAQ (1回)-(2012/08/08(Wed) 09:21:10)

分類:[VB.NET/VB2005 以降] 

環境:VB.net2008 / Win7(64Bit)

初めまして、SAQです。
1次元配列に格納されたフルパスを与え、ファイル名の部分部分を使用してソートを行い、結果を返すモジュールを作成したいのですが、
Array.SortはSubstring等の文字列を扱うメソッドが使用できず、どのようにすればいいか分かりません。
どなたかご教示願います。

例)
下記のようなフルパスがString型の1次元配列に格納されている。
C:\Folder_01\AA-001_Ver2.txt
C:\Folder_02\CC-002_Ver1.txt
C:\Folder_03\CC-003_Ver3.txt
C:\Folder_04\BB-002_Ver1.txt
C:\Folder_05\AA-001_Ver1.txt

これを、ファイル名の数字部分 / Ver部分 / 先頭のアルファベット部分
でソートを行い、下記の様な結果を返す。
(フォルダの階層は様々ですが、ファイル名には規則性があります。)

C:\Folder_05\AA-001_Ver1.txt
C:\Folder_01\AA-001_Ver2.txt
C:\Folder_04\BB-002_Ver1.txt
C:\Folder_02\CC-002_Ver1.txt
C:\Folder_03\CC-003_Ver3.txt


初歩的な質問かもしれませんが、よろしくお願い致します。


引用返信 編集キー/
■63237 / inTopicNo.2)  Re[1]: フルパスからファイル名の一部を使用してのソート
□投稿者/ sinaku (1回)-(2012/08/08(Wed) 09:52:37)
LINQを使用した方法になりますが、以下で実装ができます。
C#ですが、きっとVBでも。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var fileList =
System.IO.Directory.GetFiles(@"適当なファイルパス", @"*.*", System.IO.SearchOption.AllDirectories);

Console.WriteLine(@"ソート前");

foreach (var filePath in fileList)
{
Console.WriteLine(filePath);
}

Console.WriteLine(@"ソート後");

var sortFileList = fileList.OrderBy(a => System.IO.Path.GetFileName(a));

foreach (var filePath in sortFileList)
{
Console.WriteLine(filePath);
}

Console.ReadLine();
}
}
}


No63235 (SAQ さん) に返信
> 環境:VB.net2008 / Win7(64Bit)
>
> 初めまして、SAQです。
> 1次元配列に格納されたフルパスを与え、ファイル名の部分部分を使用してソートを行い、結果を返すモジュールを作成したいのですが、
> Array.SortはSubstring等の文字列を扱うメソッドが使用できず、どのようにすればいいか分かりません。
> どなたかご教示願います。
>
> 例)
> 下記のようなフルパスがString型の1次元配列に格納されている。
> C:\Folder_01\AA-001_Ver2.txt
> C:\Folder_02\CC-002_Ver1.txt
> C:\Folder_03\CC-003_Ver3.txt
> C:\Folder_04\BB-002_Ver1.txt
> C:\Folder_05\AA-001_Ver1.txt
>
> これを、ファイル名の数字部分 / Ver部分 / 先頭のアルファベット部分
> でソートを行い、下記の様な結果を返す。
> (フォルダの階層は様々ですが、ファイル名には規則性があります。)
>
> C:\Folder_05\AA-001_Ver1.txt
> C:\Folder_01\AA-001_Ver2.txt
> C:\Folder_04\BB-002_Ver1.txt
> C:\Folder_02\CC-002_Ver1.txt
> C:\Folder_03\CC-003_Ver3.txt
>
>
> 初歩的な質問かもしれませんが、よろしくお願い致します。
>
>
引用返信 編集キー/
■63239 / inTopicNo.3)  Re[1]: フルパスからファイル名の一部を使用してのソート
□投稿者/ shu (20回)-(2012/08/08(Wed) 10:04:23)
No63235 (SAQ さん) に返信

正規表現を使ったほうが楽でしょう。
使わなくても独自に文字列解析をすれば可能です。
以下正規表現を使ったサンプルです。


Imports System.Text.RegularExpressions

Public Class Form1
    Private Class CompSorter
        Implements IComparer(Of String)

        Private FilePat As Regex

        Public Sub New()
            FilePat = New Regex("(?<Alp>.+?)-(?<Num>\d+)_Ver(?<Ver>\d+)\.txt")
        End Sub

        Public Function Compare(x As String, y As String) As Integer Implements System.Collections.Generic.IComparer(Of String).Compare
            Dim FileX As New IO.FileInfo(x)
            Dim FileY As New IO.FileInfo(y)
            Dim xm = FilePat.Match(FileX.Name)
            Dim ym = FilePat.Match(FileY.Name)
            Compare = 0
            If xm.Success AndAlso ym.Success Then
                Dim AlpX = xm.Groups("Alp").Value
                Dim AlpY = ym.Groups("Alp").Value
                Dim NumX = CInt(xm.Groups("Num").Value)
                Dim NumY = CInt(ym.Groups("Num").Value)
                Dim VerX = CInt(xm.Groups("Ver").Value)
                Dim VerY = CInt(ym.Groups("Ver").Value)

                Dim ret = NumX.CompareTo(NumY)
                If ret = 0 Then
                    ret = VerX.CompareTo(VerY)
                End If
                If ret = 0 Then
                    ret = String.Compare(AlpX, AlpY)
                End If
                Return ret
            ElseIf xm.Success Then
                Return 1
            ElseIf ym.Success Then
                Return -1
            End If
        End Function
    End Class
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim FileNames() As String = New String() { _
                                        "C:\Folder_01\AA-001_Ver2.txt",
                                        "C:\Folder_02\CC-002_Ver1.txt",
                                        "C:\Folder_03\CC-003_Ver3.txt",
                                        "C:\Folder_04\BB-002_Ver1.txt",
                                        "C:\Folder_05\AA-001_Ver1.txt"
                                    }
        Dim Sorter As New CompSorter

        Array.Sort(FileNames, Sorter)
    End Sub
End Class

引用返信 編集キー/
■63240 / inTopicNo.4)  Re[2]: フルパスからファイル名の一部を使用してのソート
□投稿者/ sinaku (2回)-(2012/08/08(Wed) 10:23:42)
いちよう追記

> ファイル名の数字部分 / Ver部分 / 先頭のアルファベット部分

ソートするためのキーがファイル名称の一部を並び替えて行う場合、私が書いたLINQから、
対象となる文字列を変更してソートして下さいな。

あとはshuさんのおっしゃってる通り、正規表現でみてもいいですし、
クラス一つ作ってIComparer実装してソートをしてもいいです。

IComparerやIComparableなどを実装した場合は、そのままListのSortで並び替えが出来ます。
引用返信 編集キー/
■63243 / inTopicNo.5)  Re[3]: フルパスからファイル名の一部を使用してのソート
□投稿者/ SAQ (3回)-(2012/08/08(Wed) 10:47:51)
>sinakuさん
レス有難うございます。
LINQというものを初めて知りました。
まずはLINQについて調べ、記載頂いたサンプルコードを理解できるように勉強したいと思います。
また、補足もしていただき有難うございます。
大変参考になります。


>shuさん
レス有難うございます。
正規表現は使ったことが無いのですが、サンプルコードを拝見させていただき、
他の場面でも流用可能なように感じました。
ファイル名についてはルールに則って管理するようにしているので、
実装はこちらの方法で行きたいと思います。
有難うございました。

(テストプログラムの作成後[解決済み]にしたいと思います。)

引用返信 編集キー/
■63245 / inTopicNo.6)  Re[4]: フルパスからファイル名の一部を使用してのソート
□投稿者/ sinaku (3回)-(2012/08/08(Wed) 10:59:22)
さらについき。

文字列かえてやってくださいっとなげっぱなしもなんなので、サンプルとして別途追記。

var sortFileList =
fileList.OrderBy(
a => string.Format(@"{0}{1}",new object[]{System.IO.Path.GetExtension(a), System.IO.Path.GetFileNameWithoutExtension(a)}));

今回追加したのは、拡張子+ファイル名でソートしてるパターン。

OrderByの中で対象となる文字列をどうしたいかきめればOK

なんで、たとえば今回質問にあったのであれば、
string.Format(@"{0}{1}{2}", new object[]{数字部分 / Ver部分 / 先頭のアルファベット部分})

これをOrderBy句で指定してあげればOK

お勉強がんばってくらはいねー
引用返信 編集キー/
■63433 / inTopicNo.7)  Re[5]: フルパスからファイル名の一部を使用してのソート
□投稿者/ SAQ (5回)-(2012/08/24(Fri) 10:48:17)
お礼が遅くなり申し訳ありません。

Shuさんに頂いたサンプルコードを一部変更し、
一応、目的の処理は実装できました。有難うございました。

現在、他のケースにも対応できるようにして欲しいという要望があったため、
コードを作成中ですが少々難航しております...(^^;
聞いてばかりでは成長できないので、しばらく試行錯誤してみたいと思います。

>sinakuさん
追記有難うございました。
LINQについても併せて勉強中です。
ついでにSQLについても調べていますが、未知の領域だったため先が長そうです(汗


「どうにもこうにも…」となったらまた質問させて頂きたく存じます。
色々とご教示頂き有難うございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -