web-dev-qa-db-ja.com

Orderby()が番号を正しく並べていないc#

私は自分の会社用のアプリを書いており、現在検索機能に取り組んでいます。ユーザーがアイテムを検索するときに、最新のバージョン(データベースに保存されているバージョン)を表示したいと思います。

問題は、バージョンがintではなく文字列として保存され、結果に対してOrderBy(q => q.Version)を実行すると、次のように返されることです。

1
10
11
2
3
...

明らかに2は10の前に来ます。

バージョンを整数としてキャストする方法はありますか、それとも単純なIComparerがありますか?これまでのところ、実質的なものは何も見つかりませんでした。

私はこれをやってみました:

var items = (from r in results
             select r).OrderBy(q => Int32.Parse(q.Version));

これはコンパイルされますが動作しません。

37
Darcy

Int32.Parseは、LinqToSqlトランスレータではサポートされていません。 Convert.ToInt32がサポートされています。

http://msdn.Microsoft.com/en-us/library/sf1aw27b.aspx

http://msdn.Microsoft.com/en-us/library/bb882655.aspx

26
Amy B

あなたの問題はどこかにあります、次の作品:

new[] { "1", "10", "2", "3", "11" }
    .OrderBy(i => int.Parse(i))
    .ToList()
    .ForEach(Console.WriteLine);

問題がLINQ to SQLの場合、CLRがLINQからSQLを作成しようとしており、int.Parseを理解できません。あなたができることは、最初にSQLからデータを取得し、すべてのデータがロードされたらそれを注文することです:

var items = (from r in results
             select r)
            .ToList()
            .OrderBy(q => Int32.Parse(q.Version));

それを行う必要があります。

7

テーブル定義を変更できず(バージョンが数値型であるため)、クエリが実際にリストされているとおりである(スキップ、テイク、またはその他の方法で結果の数を減らしていない)場合、最善の方法並べ替えられていない結果に対して "ToList"を呼び出します。これにより、OrderBYラムダを適用すると、SQL Server側で実行するのではなく、コードで実行されます(これで機能するはずです)。

なぜラムダでソートするのですか?クエリを並べ替えてみませんか?

var query = from r in items
            orderby int.Parse( r )
            select r;

LINQ to SQLを使用していることがわかったので、次のような方法で標準のSQL呼び出しを行うことを検討してください。

Select ..., Cast( TextWhichShouldBeIntCol As int ) As IntCol
From ...

あるいは

Select ..., Cast( TextWhichShouldBeIntCol As int ) As IntCol
From ...
Order By Cast( TextWhichShouldBeIntCol As int )

これは、intとしてLINQに流れ込みます(2番目の反復を使用する場合は、順序付けされます)。これにより、LINQで結果セットを2回実行する必要がなくなります(クエリの場合は1回、順序付けの場合は1回)。

5
Thomas

自然な並べ替えに関しては、すばらしい仕事をする素晴らしいコードがあります。その名前は AlphanumComparator

サンプルコード:

var ordered = Database.Cars.ToList().OrderBy(c => c.ModelString, new AlphanumComparator());

リストはメモリ内になければならないことに注意してください。

C#バージョンを取得した場合は、次のようにします。

AlphanumComparator : IComparer<string>

そして

public int Compare(string x, string y)
5
var items = (from r in results
         select r).OrderBy(q => Convert.ToInt32(q.Version));

間違いなく実行......

1
Sunil Dhanerwal

テストをしました。次のコードがあります。

_string[] versions = { "1", "2", "10", "12", "22", "30" };
foreach (var ver in versions.OrderBy(v => v))
{
     Console.WriteLine(ver);
}
_

予想通り、結果は1、10、12、2、22、30になります。次に、versions.OrderBy(v => v))versions.OrderBy(v => int.Parse(v)))に変更します。そしてそれはうまくいきます:1、2、10、12、22、30

あなたの問題は、あなたの文字列に '。'のような数字でない文字が含まれていることだと思います。どのような例外がありますか?

1
ILya

「最新バージョン」だけが必要なのに、なぜソートするのですか? Max()を使用すると、オーバーヘッドを回避できるようです。

また、列のタイプを整数に変更する必要があります。

1

これを試して:

var items = results.(Select(v => v).OrderBy(v => v.PadLeft(4));

それはLinq2Sqlで動作します

1
Mike Jacobs

数値ではなくテキスト値があるようです。

並べ替える必要がある場合は、次のことを試してください。

var items = (from r in results
             select r);
return items.OrderBy( v=> Int.Parse(v.Version) );
0
chris
var query = from r in items
            let n = int.Parse(r)
            orderby n
            select n;
0
Alxandr
var items = (from v in results
                    select v).ToList().OrderBy(x => int.Parse(x.Version));
0
Steven Williams