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

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

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

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

Q&A

解決済

5回答

3062閲覧

Linqを使わずにGroupByやSelectを実現したい

widget11

総合スコア221

C#

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

0グッド

0クリップ

投稿2019/07/10 08:13

以下のようなコードがあって

class Food { public string Name { get; set; } public decimal Amount { get; set; } } //以下別クラス var food = new List<Food>(); food.GroupBy(x => x.Name) .Select(x => new Food() { Name = x.Key, Amount = x.Sum(y => y.Amount) }) .ToList();

やってるいこととしては変数foodにListで[[肉, 100g],[魚, 80g],[肉, 50g],[米, 120g]]のような形で、食べ物とその重さが入っています。
そしてこれを名前でグループ化し、[[肉, 150g],[魚, 80g],[米, 120g]]というような形にしているのですが、
これをLinqやラムダを使ったメソッド式で表さないようにしてList化したいのですがどうすればよいのでしょうか。
上手くロジックを思いつかず悩んでおります。具体的にはgrou_byとselect newメソッドをLinqを使わずに表現したいです。
ちなみにLinqを使わない理由としては、このコードがLinqを習っていない人の為に研修のサンプルコードであるという理由です。
よろしくお願い致します。

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

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

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

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

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

x_x

2019/07/10 08:16

先に LINQ を教えたほうがいいのでは?
widget11

2019/07/10 08:22

どうしてもLinq教えたらダメらしく。。。 僕が分からないのに教えるのもどうかと思うのですが。。。。
papinianus

2019/07/10 09:26

ラムダはilからコードを取り出せばワンチャン。 しかし、質問者様の発言を信じればこれはプログラミングの問題ではなく社内政治の問題です。teratailでは解決不能です。 linqを教えたらダメ、というのはVisualStudioを使わずメモ帳でコーディングしろというような不合理を感じます。
guest

回答5

0

普通にループを使えばいいのでは?

投稿2019/07/10 08:29

Zuishin

総合スコア28656

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

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

Zuishin

2019/07/10 08:32

というか状況がかなり不自然ですが、元々のLINQ 式はどこからとってきたのでしょう? LINQ の理解度を確かめるために、LINQ 式をループに直しなさいという課題ではありませんか?
Zuishin

2019/07/10 08:34

過去の質問を見ても、研修を受けさせる立場ではなく受けている立場のようにしか思えません。
guest

0

大体こんな感じになりますが、LINQ のほうが楽では?

C#

1 class FoodEqualityComparer : IEqualityComparer<Food> 2 { 3 public bool Equals(Food x, Food y) 4 { 5 return x.Name == y.Name; 6 } 7 8 public int GetHashCode(Food obj) 9 { 10 var b = obj.Name + ":" + obj.Amount.ToString(); 11 return b.GetHashCode(); 12 } 13 }

C#

1 var result = new List<Food>(); 2 var comparer = new FoodEqualityComparer(); 3 foreach (var x in food) 4 { 5 if (result.Contains(x, comparer)) 6 { 7 result.Find(delegate (Food f) { return f.Name == x.Name; }).Amount += x.Amount; 8 } 9 else 10 { 11 result.Add(x); 12 } 13 }

投稿2019/07/10 09:02

x_x

総合スコア13749

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

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

x_x

2019/07/10 09:04

ラムダ書かない代わりに delegate を書かなきゃいけないのって逆に大変そう
guest

0

ベストアンサー

こんにちは。

動作速度を気にせず発注通りに書くとたぶんこうです。

csharp

1 2 public class Food 3 { 4 public string Name { get; set; } 5 public decimal Amount { get; set; } 6 } 7 8 private void button_Click(object sender, RoutedEventArgs e) 9 { 10 // 元のデータはこれ。 11 var foods = new[] { 12 new Food() { Name = "肉", Amount = 100 }, 13 new Food() { Name = "魚", Amount = 80 }, 14 new Food() { Name = "肉", Amount = 50 }, 15 new Food() { Name = "米", Amount = 120 }, 16 }; 17 18 var result = new List<Food>(); 19 foreach (var food in foods) // 一つずつ処理します。 20 { 21 22 // 自分と同じ名前のFoodがresultに存在するかを確認します。Findとか使ってよければそちらでもOK 23 Food sameNameFood = null; 24 foreach (var foodInResult in result) 25 { 26 if (foodInResult.Name == food.Name) 27 { 28 sameNameFood = foodInResult; 29 break; 30 } 31 } 32 33 if (sameNameFood != null) 34 { 35 // 見つかった場合は重さを加算します。 36 sameNameFood.Amount += food.Amount; 37 } 38 else 39 { 40 // 見つからない場合は新規に追加します。 41 result.Add(new Food() { Name = food.Name, Amount = food.Amount }); 42 } 43 } 44 45 // 結果を出力 46 foreach (var food in result) 47 { 48 Trace.WriteLine($"{food.Name}, {food.Amount}g"); 49 } 50 }

投稿2019/07/10 08:38

takabosoft

総合スコア8356

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

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

YAmaGNZ

2019/07/10 08:50

「LINQを使わない」であれば、FindやFindIndexが使えるのではないでしょうか?
takabosoft

2019/07/10 09:36 編集

LINQナシ縛りをしている人にそこの区別が付くかは怪しいですよね^^;
guest

0

x番目の要素のNameと同一のNameを持つ要素が 0~x-1 番目までに存在するかどうかを調べて,
存在する場合には,そいつのAmountにx番目の要素のAmountを加算して,x番目の要素を捨てる
ということを適当なループを書いてやれば良い
(最初にNameでソートしていいならNameが同じ範囲が探しやすくて楽かな.)
…という話ではないのでしょうか.


具体的にはgrou_byとselect newメソッドをLinqを使わずに表現したいです。

2つの処理を分けて書かないといけないのかな?
とりあえず超てきとーだけど,こんなもんを書けば良いのだろうか?

static Dictionary<string,List<Food>> TheGroupByName( IEnumerable<Food> Src ) { var Ret = new Dictionary<string,List<Food>>(); foreach( var S in Src ) { if( !Ret.ContainsKey( S.Name ) ){ Ret.Add( S.Name, new List<Food>() ); } Ret[ S.Name ].Add( new Food(){ Name = S.Name, Amount = S.Amount } ); } return Ret; } static List<Food> TheSelectSumAmount( Dictionary<string,List<Food>> Grouped ) { var Ret = new List<Food>( Grouped.Keys.Count ); foreach( var G in Grouped ) { decimal SumAmount = 0; foreach( var S in G.Value ){ SumAmount += S.Amount; } Ret.Add( new Food(){ Name=G.Key, Amount=SumAmount } ); } return Ret; } //使う側 var Result = TheSelectSumAmount( TheGroupByName( foods ) );

投稿2019/07/10 08:28

編集2019/07/10 09:01
fana

総合スコア11634

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

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

0

ReSharperとか使えばその手の変換は簡単にできたと思うので、仕事で必要ならライセンス買ってみれば良いと思いますが。(継続的に必要になるんだろうし)

投稿2019/07/10 11:32

gentaro

総合スコア8949

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問