質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

Q&A

解決済

4回答

1040閲覧

[C#][LINQ] 単語を「あ、い、う、......、ん、A、B、......、W」の優先順位で並び替えたい。

chatanisota

総合スコア31

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

0グッド

0クリップ

投稿2021/12/08 08:01

現在、C#とLINQを勉強している初学者です。
簡単な辞書のサンプルを作成に挑戦していますが、以下の事象で詰まってしまいました。
ご指南、コメントいただければ幸いです。。。

実現したいこと

単語のリストをLINQを用いて、「あ、い、う、......、ん、A、B、......、W」の優先順位で順番に並び替えたいです。

理想) ・並び替え前 「こたつ」「CD」「うさぎ」「ゆき」「TV」 ・並び替え後 「うさぎ」「こたつ」「ゆき」「CD」「TV」

今できていること

LINQのOrderByを用いて並び替えを行うと、「A、B、......、W、あ、い、う、......、ん」の優先順位で並び替えを行ってくれます。

現状) ・並び替え前 「こたつ」「CD」「うさぎ」「ゆき」「TV」 ・並び替え後 「CD」「TV」「うさぎ」「こたつ」「ゆき」

ソースコード

C#

1class Tango{ 2 public string Moji; 3 public string Yomi; 4} 5 6List<Tango> items = ... // 単語の初期化 7items = items.OrderBy(o => o.Yomi).ToList();

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/12/08 08:49

質問に CD とか TV とか書いてありますが、それらの文字列は全てアルファベットだけなのですか?
chatanisota

2021/12/08 09:02

追記ありがとうございます。「TVかめら」「みにALBUM」といった複合型もあります。
退会済みユーザー

退会済みユーザー

2021/12/08 09:11

それだと何ともならない、少なくとも一筋縄ではいかないと思います。ちょっとお付き合いしかねますので、お役に立てずすみませんが、他の方の回答をお待ちください。
dodox86

2021/12/08 09:41

出現する「文字」は「あ、い、う、......、ん、A、B、......、W」のみでしょうか。
Zuishin

2021/12/08 10:14 編集

戦略としては chatanisota さんの回答のように IComparer<string> を作ることになりますが、Comparer<T> というクラスがあるので、そこから派生させるのが良いでしょう。 あるいは派生させず Create メソッドからオブジェクトを作成することもできます。 文字列同士の比較では目的のものはないので、自分で比較メソッドを作る必要があります。 Enumerable.Zip<char> を使えば、短い方の文字列に合わせて文字毎の比較ができますので、これで行い、大小の差が出なかった場合に文字数の短い方を小さいと判定すれば良いと思います。 文字列同士の比較から呼び出される文字同士の比較ですが、ひらがなとアルファベットの違いをどう求めるかは、どのような文字が許されるのかによって多少戦略が変わってきますが、この質問のみから判断するなら、Char.IsAscii メソッドを使えば良いと思います。 スイッチ式が使えるのであれば、(char a, char b) => (Char.IsAscii(a), Char.IsAscii(b)) switch { (false, false) or (true, true) => a - b, (false, true) => -1, (true, false) => 1 } のように文字同士の比較ができます。
guest

回答4

0

ベストアンサー

カルチャ(InvariantCulture, CurrentCulture)を考慮するとやっかいなので
CompareOrdinal を使うことにします。

アルファベットに「ん」を加算しただけだと、「ん」のあとの文字とアルファベットが
同値になってしまうので文字コードをブロック単位で考えます。

(1) A より小さい
(2) A ~ Z
(3) Z より大きく「ん」まで
(4) 「ん」より大きい

欲しい並びは

(1)(3)(2)(4)

になるので、(3) の部分は (-26)、(2) の部分は (+「ん」のコード + 1 - 26) してやればいいわけです。
になるので、(3) の部分は (-26)、(2) の部分は (- 'A' +「ん」のコード - 26) してやればいいわけです。

小文字はどうするのとか、カナはどうするのとかありますが、考え方はいっしょです。

C#

1class Program 2{ 3 static void Main(string[] args) 4 { 5 string[] array = { "こたつ", "CD", "うさぎ", "ゆき", "TV" }; 6 Array.Sort(array, new CompareChar()); 7 foreach (var item in array) { 8 Console.WriteLine(item); 9 } 10 Console.ReadKey(); 11 } 12 13 private class CompareChar : IComparer<string> 14 { 15 public int Compare(string str1, string str2) 16 { 17 str1 = Convert(str1); 18 str2 = Convert(str2); 19 return string.CompareOrdinal(str1, str2); 20 } 21 22 private static string Convert(string str) 23 { 24 var sb = new System.Text.StringBuilder(); 25 if (str != null) { 26 foreach (char c in str) { 27 char code; 28 if (c >= 'A' && c <= 'Z') { 29 //code = (char)(c + 'ん' - 25); 30 code = (char)(c - 'A' + 'ん' - 26); 31 } else if (c > 'Z' && c <= 'ん') { 32 code = (char)(c - 26); 33 } else { 34 code = c; 35 } 36 sb.Append(code); 37 } 38 } 39 return sb.ToString(); 40 } 41 } 42}

投稿2021/12/08 12:52

編集2021/12/09 01:34
KOZ6.0

総合スコア2626

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

出現する文字が「あ、い、う、......、ん、A、B、......、W」のみなら下記のような方法はどうでしょうか。

using System; using System.Linq; using System.Collections.Generic; public class Program{ public static void Main(){ var items = new List<Tango>(){ new Tango { Yomi = "こたつ" }, new Tango { Yomi = "CD" }, new Tango { Yomi = "うさぎ" }, new Tango { Yomi = "ゆき" }, new Tango { Yomi = "TV" } }; var mySortedCharacters = "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをんABCDEFGHIJKLMNOPQRSTUVW"; foreach(var item in items.OrderBy(x => mySortedCharacters.IndexOf(x.Yomi[0]))){ Console.WriteLine(item.Yomi); } // うさぎ // こたつ // ゆき // CD // TV } } public class Tango{ public string Moji; public string Yomi; }

希望する順番に文字を並べた文字列 mySortedCharacters を用意し、各 Tango オブジェクトが持つ Yomi プロパティの1文字目が mySortedCharacters の何番目に属するかで並び替えを行っています。

投稿2021/12/08 12:20

編集2021/12/08 12:24
BluOxy

総合スコア2663

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

その比較関数を、ひらがなを先に、アルファベットをあとにするように結果を返すように書きましょう

投稿2021/12/08 11:29

y_waiwai

総合スコア87747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

追記・検証

自作比較関数を作成して、比較を行おうと試みました。

C#

1private class CompareChar : IComparer<string> 2{ 3 // IComparerインターフェース用の比較関数 4 public int Compare(string str1, string str2) 5 { 6 for (int i = 0; i < str1.Length; i++) 7 { 8 if ('a' <= str1[i] && str1[i] <= 'Z') 9 { 10 str1[i] += 'ん'; 11 } 12 } 13 for (int i = 0; i < str2.Length; i++) 14 { 15 if ('a' <= str2[i] && str2[i] <= 'Z') 16 { 17 str2[i] += 'ん'; 18 } 19 } 20 return str1.CompareTo(str2); 21 } 22}

しかしながら以下の問題があります。

  • str1[i]+='ん'のような加算代入はできない
  • もっとシンプルに記述したい

投稿2021/12/08 09:21

chatanisota

総合スコア31

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YT0014

2021/12/08 10:22

解決になっていないのを確認されているのなら、質問文を編集して追記するのが良いかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問