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

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

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

Re[8]: 複数キーによるソートについて


(過去ログ 45 を表示中)

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

■23881 / inTopicNo.1)  複数キーによるソートについて
  
□投稿者/ ぽっぽ(初心者) (1回)-(2008/08/23(Sat) 00:51:41)

分類:[VB.NET/VB2005] 

VB.net2008 XPです。

単体キーならArrayクラスのSortで並び替えできるのですが
複数キーになると難しくて書けません;;

Compareを使って実現するという所までわかったのですが
3つのキーがあり、その3つのキーはそれぞれ
1キー 昇順 降順 ソートしない
2キー 昇順 降順 ソートしない
3キー 昇順 降順 ソートしない
という風になっており、どのキーでソートされるかがわからない状態です。

並び替えするデータは
Dim Datas() As データ
Public Structure データ
Public key1 As String
Public key2 As String
Public key3 As String
End Structure
のような形になっており、考えているとわけわからなくなってきます。。。

どのようにして書いていけば良いでしょうか
よろしくお願いします
引用返信 編集キー/
■23883 / inTopicNo.2)  Re[1]: 複数キーによるソートについて
□投稿者/ も (31回)-(2008/08/23(Sat) 01:44:29)
No23881 (ぽっぽ(初心者) さん) に返信
> VB.net2008 XPです。
分類と利用されてる環境がちょっと一致しないような…プロジェクトが2005を対象にしたものと考えてよろしいでしょうか?

> 単体キーならArrayクラスのSortで並び替えできるのですが
> 複数キーになると難しくて書けません;;
>
> Compareを使って実現するという所までわかったのですが
> 3つのキーがあり、その3つのキーはそれぞれ
> 1キー 昇順 降順 ソートしない
> 2キー 昇順 降順 ソートしない
> 3キー 昇順 降順 ソートしない
> という風になっており、どのキーでソートされるかがわからない状態です。
”どのキーでソートされるかがわからない”のと”ソートの仕方が分からない”のでは意味が違います.
少なくともソートの仕方は分かっている状態ですか?

たとえばどのキーも”ソートしない”場合はどのような仕方でソートされるのでしょうか?

> 並び替えするデータは
> Dim Datas() As データ
> Public Structure データ
> Public key1 As String
> Public key2 As String
> Public key3 As String
> End Structure
> のような形になっており、考えているとわけわからなくなってきます。。。
どのような形で考えていますか?
たとえば {key1 = "a", key2 = "bc", key3 = "d"} と {key1 = "d", key2 = "ab", key3 = "e"} の
2種類ではそれぞれのソートの仕方の場合でどのような順になるとお考えですか?
引用返信 編集キー/
■23884 / inTopicNo.3)  Re[2]: 複数キーによるソートについて
□投稿者/ επιστημη (1276回)-(2008/08/23(Sat) 02:16:07)
επιστημη さんの Web サイト
2008/08/23(Sat) 18:00:57 編集(投稿者)
Imports System
Imports System.Collections.Generic

Public Structure データ
  Public key1 As String
  Public key2 As String
  Public key3 As String
End Structure

Public Class MultiKeyComp(Of T)
  Implements IComparer(Of T)

  Dim comps() As Comparison(Of T)

  Public Function Compare(ByVal x As T, ByVal y As T) As Integer _
    Implements IComparer(Of T).Compare
    For Each c As Comparison(Of T) In comps
      Dim result As Integer = c(x, y)
      If result <> 0 Then Return result
    Next
    Return 0
  End Function

  Public Sub New(ByVal ParamArray c() As Comparison(Of T))
    comps = c
  End Sub

End Class

Public Class Program

  Shared Function lt1(ByVal x As データ, ByVal y As データ) As Integer
    Return x.key1.CompareTo(y.key1)
  End Function
  Shared Function gt1(ByVal x As データ, ByVal y As データ) As Integer
    Return y.key1.CompareTo(x.key1)
  End Function
  Shared Function lt2(ByVal x As データ, ByVal y As データ) As Integer
    Return x.key2.CompareTo(y.key2)
  End Function
  Shared Function gt2(ByVal x As データ, ByVal y As データ) As Integer
    Return y.key2.CompareTo(x.key2)
  End Function
  Shared Function lt3(ByVal x As データ, ByVal y As データ) As Integer
    Return x.key3.CompareTo(y.key3)
  End Function
  Shared Function gt3(ByVal x As データ, ByVal y As データ) As Integer
    Return y.key3.CompareTo(x.key3)
  End Function
  Shared Function non(ByVal x As データ, ByVal y As データ) As Integer
    Return 0
  End Function

  Public Shared Sub Main()
    Dim N As Integer = 10
    Dim data(N - 1) As データ
    Dim r As New Random()
    For i As Integer = 0 To N - 1
      Dim datum As New データ()
      With datum
        .key1 = r.Next(10).ToString()
        .key2 = r.Next(10).ToString()
        .key3 = r.Next(10).ToString()
      End With
      data(i) = datum
    Next

    Console.WriteLine("ソート前")
    For Each item As データ In data
      Console.WriteLine("{0} {1} {2}", item.key1, item.key2, item.key3)
    Next
    Console.WriteLine()

    ' 昇順,ソートせず,降順 でソートする
    Dim c As New  _
      MultiKeyComp(Of データ)(AddressOf lt1, _
                              AddressOf non, _
                              AddressOf gt3)
    Array.Sort(data, c)

    Console.WriteLine("ソート後")
    For Each item As データ In data
      Console.WriteLine("{0} {1} {2}", item.key1, item.key2, item.key3)
    Next
  End Sub

End Class

引用返信 編集キー/
■23885 / inTopicNo.4)  Re[3]: 複数キーによるソートについて
□投稿者/ やじゅ (565回)-(2008/08/23(Sat) 08:17:25)
やじゅ さんの Web サイト
私なら、Array型ではなくDataTable型にします。

Dim dtData As DataTable

dtData = New DataTable
dtTable.Columns.Add("key1", GetType(String))
dtTable.Columns.Add("key2", GetType(String))
dtTable.Columns.Add("key3", GetType(String))

ここで、dtDataにデータを格納してもらう。


条件によって、ソート順を指定した文字列を生成します。

SortOrder = "key1 ASC,key2 DESC,key3 ASC"
DataView ソート
http://msdn.microsoft.com/ja-jp/library/system.data.dataview.sort(VS.80).aspx

データビュー型でソートを指定
Dim dvView As DataView
dvView = dtTable.DefaultView
dvView.Sort = SortOrder

DataTableやDataViewの使い方は覚えると便利ですよ。
引用返信 編集キー/
■23887 / inTopicNo.5)  Re[4]: 複数キーによるソートについて
□投稿者/ 鶏唐揚 (286回)-(2008/08/23(Sat) 09:54:40)
2008/08/23(Sat) 09:55:08 編集(投稿者)
>分類と利用されてる環境がちょっと一致しないような…プロジェクトが2005を対象にしたものと考えてよろしいでしょうか?
単純に項目にVB2008がない&「VB.NET」とあるのでVB2008も含まれる と考えての選択ではないでしょうか。

もしターゲットが.NETFramework3.5であればLINQ使えば楽です。

Key1の昇順かつKey2の降順で並べてみます


Dim SortedDatas = From n In Datas _
                  Order By n.Key1 Ascending, n.Key2 Descending

For i As Integer = 0 To Datas.Length - 1
    Datas(i) = SortedDatas(i)
Next


ただし構造体メンバーに参照型が含まれると、Forループでのコピー時に
注意が必要です。

引用返信 編集キー/
■23888 / inTopicNo.6)  Re[5]: 複数キーによるソートについて
□投稿者/ やじゅ (567回)-(2008/08/23(Sat) 10:26:54)
やじゅ さんの Web サイト
No23887 (鶏唐揚 さん) に返信
> もしターゲットが.NETFramework3.5であればLINQ使えば楽です。
>

ソート式が条件によって変更になる仕様なので
文字列で使用可能にする動的LINQにしないとね。
http://devadjust.exblog.jp/7107642/

引用返信 編集キー/
■23889 / inTopicNo.7)  Re[5]: 複数キーによるソートについて
□投稿者/ れい (752回)-(2008/08/23(Sat) 10:30:24)
2008/08/23(Sat) 10:30:34 編集(投稿者)
おー。
みんないろいろな手を使いますねぇ

DataTableを使うのが楽な気がしますが、私はあまりすきじゃないです。
私ならIComparerを使って比較用のクラスをつくります。


    Public Structure data
        Public key1 As String
        Public key2 As String
        Public key3 As String
    End Structure

    Public Enum SortType
        None
        Ascendant
        Desccendant
    End Enum

    Public Class DataComparer
        Implements IComparer(Of data)
        Private key1sorttype As SortType
        Private key2sorttype As SortType
        Private key3sorttype As SortType

        Public Sub New(ByVal key1sorttype As SortType, ByVal key2sorttype As SortType, ByVal key3sorttype As SortType)
            Me.key1sorttype = key1sorttype
            Me.key2sorttype = key2sorttype
            Me.key3sorttype = key3sorttype
        End Sub

        Public Function Compare(ByVal x As data, ByVal y As data) As Integer Implements System.Collections.Generic.IComparer(Of data).Compare
            Dim r As Integer
            Select Case Me.key1sorttype
                Case SortType.Ascendant
                    r = String.Compare(x.key1, y.key1)
                Case SortType.Desccendant
                    r = -String.Compare(x.key1, y.key1)
            End Select
            If r <> 0 Then Return r
            Select Case Me.key1sorttype
                Case SortType.Ascendant
                    r = String.Compare(x.key2, y.key2)
                Case SortType.Desccendant
                    r = -String.Compare(x.key2, y.key2)
            End Select
            If r <> 0 Then Return r
            Select Case Me.key1sorttype
                Case SortType.Ascendant
                    r = String.Compare(x.key3, y.key3)
                Case SortType.Desccendant
                    r = -String.Compare(x.key3, y.key3)
            End Select
            Return r
        End Function

    End Class

    Public Sub sort(ByVal parameter As data(), ByVal key1sorttype As SortType, ByVal key2sorttype As SortType, ByVal key3sorttype As SortType)
        Array.Sort(parameter, New DataComparer(key1sorttype, key2sorttype, key2sorttype))
    End Sub

こんな感じで。



引用返信 編集キー/
■23894 / inTopicNo.8)  Re[6]: 複数キーによるソートについて
□投稿者/ 渋木宏明(ひどり) (862回)-(2008/08/23(Sat) 11:59:05)
渋木宏明(ひどり) さんの Web サイト
> 文字列で使用可能にする動的LINQにしないとね。

条件式の expression tree を動的に組み立てるとか。

あるいは、場合の数が少ないならすべてのパターンを書いておいて、どれを実行するか実行時に選択するとか。

引用返信 編集キー/
■23897 / inTopicNo.9)  Re[7]: 複数キーによるソートについて
□投稿者/ επιστημη (1277回)-(2008/08/23(Sat) 12:26:23)
επιστημη さんの Web サイト
2008/08/23(Sat) 12:26:42 編集(投稿者)
↓C#らむだ版

using System;

namespace MultiKey_cs {

  /*
   * ぶっちゃけキモはこいつだけ。
   */
  class MultiKeyComp<T> : System.Collections.Generic.IComparer<T> {
    private Comparison<T>[] comps;

    public MultiKeyComp(params Comparison<T>[] c) {
      comps = c;
    }

    public int Compare(T x, T y) {
      int result = 0;
      foreach ( Comparison<T> c in comps ) {
        if ( (result = c(x, y)) != 0 ) break;
      }
      return result;
    }

  }

  public struct データ {
    public string key1;
    public string key2;
    public string key3;
  }

  public class Program {
    public static void Main() {
      int N  = 10;
      データ[] data = new データ[N];
      Random r = new Random();
      for ( int i = 0; i < N; ++i ) {
        データ datum = new データ();
        datum.key1 = r.Next(10).ToString();
        datum.key2 = r.Next(10).ToString();
        datum.key3 = r.Next(10).ToString();
        data[i] = datum;
      }

      Console.WriteLine("ソート前");
      Array.ForEach(data, 
        x => Console.WriteLine("{0} {1} {2}", x.key1, x.key2, x.key3));
      Console.WriteLine();

      Array.Sort(data,
                 new MultiKeyComp<データ>(
                  (x,y) => x.key1.CompareTo(y.key1), // key1:昇順
                  (x,y) => 0,                        // key2:don't care
                  (x,y) => y.key3.CompareTo(x.key3)  // key3:降順
                 )
                );

      Console.WriteLine("ソート後");
      Array.ForEach(data, 
        x => Console.WriteLine("{0} {1} {2}", x.key1, x.key2, x.key3));
      Console.WriteLine();
    }
  }
}

引用返信 編集キー/
■23907 / inTopicNo.10)  Re[8]: 複数キーによるソートについて
□投稿者/ ぽっぽ(初心者) (2回)-(2008/08/23(Sat) 17:29:23)
皆さん回答ありがとうございます。

今見ている最中なのですが
いろいろ調べることが沢山ありそうなので、返事が遅くなりそうです。

すみません。。
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -