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

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

ただいまの
回答率

90.53%

  • C#

    7066questions

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

List<独自クラス>内での特定プロパティの合算方法

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 134

hiro24

score 4

いつもお世話になっております。

C#の初学者です。

以下の動作を目的をするWindows Formアプリを作成している中で、書籍やネットで検索してもどうしても解決できなかったため投稿させていただきました。

【開発環境】
・OS:Windows 10
・Visual Studio 2017 ver.15.7.3
・.NET ver.4.7.02556

【目的】
[1]CSVファイルを読み込む(※取り込み内容:【目的の動作(例)】の入力ファイル参照)
[2]読み込んだCSVファイルをList化し、ListViewに表示する
[3]List内で同一店舗名、同一コード、同一レートのもがすでに存在している場合、販売数量をそのすでに存在しているListに加算する。※1種類しか存在しないものはそのまま表示する。

文章ではわかりにくいと思いますので詳細は、【目的の動作(例)】の画像を参照の程お願いいたします。

【目的の動作(例)】
イメージ説明
例1)青塗りのデータ
店舗名:A、商品コード:111、割引率:1が共通している。そのためこれらを一つにまとめた販売数:100+200=300の結果を出力する

例2)オレンジ塗りのデータ(例1と同内容)
店舗名:B、商品コード:222、割引率:2が共通している。そのためこれらを一つにまとめた販売数:300+500=800の結果を出力する

※色塗りなしは、1種類しかないためそのまま表示。

上記の画像をご覧いただくとわかるように、同じ店舗もしくは商品コードでも割引率が違うものなどが存在します。
これらも区別して上記のような結果を得られる動作が欲しいと考えています。

【困っていること】
・CSVを順次読み込んでいく中でList内で同一店舗名、同一コード、同一レートでがすでに存在している場合、数量をそのすでに存在しているListに加算するやり方がわからないこと。(目的の[3])

【現在までで出来ていること】
以下のようにCSVをListViewに表示するところまではできています。(目的の[1],[2])
イメージ説明

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Reflection;
using System.Globalization;
using System.IO;

namespace Excel_convert
{
    public partial class Form1 : Form
    {
        public myconvertor myapp = new myconvertor();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog();

            if (System.IO.File.Exists(openFileDialog1.FileName))
            {

                myapp.Caliculate(openFileDialog1.FileName);
                myapp.mydata.filuplv(myapp.SaleDatas_output, "", listView1);

            }
        }
    }

    public class filedumprecov
    {

        public List<ListViewItem> LV<t>(List<t> mylist)
        {
            List<ListViewItem> myitems;
            ListViewItem myitem;
            myitems = new List<ListViewItem>();
            PropertyInfo[] properties = typeof(t).GetProperties();

            int k = 0;

            foreach (t exp in mylist)
            {
                string[] tempstring = new string[properties.Count()];
                bool isred = false;
                int i = 0;

                foreach (PropertyInfo prop in properties)
                {
                    tempstring[i] = Convert.ToString(prop.GetValue(exp));

                    if (prop.PropertyType == typeof(Int32))
                    {
                        int mynumber = Convert.ToInt32(prop.GetValue(exp));
                        if (mynumber < 0) { isred = true; }
                    }

                    i++;

                }

                myitem = new ListViewItem(tempstring);
                if (isred)
                {
                    myitem.ForeColor = Color.Red;
                }
                k++;
                myitems.Add(myitem);
            }
            return myitems;
        }



        public void filuplv<t>(List<t> mylist, string myheader, ListView myLV)
        {

            string[] columns = myheader.Split(',');
            PropertyInfo[] properties = typeof(t).GetProperties();

            if (columns.Count() < 2)
            {
                columns = new string[properties.Count()];
                for (int i = 0; i < properties.Length; i++) { columns[i] = properties[i].Name; }
            }

            myLV.Clear();
            myLV.View = View.Details;
            myLV.GridLines = true;
            myLV.FullRowSelect = true;

            for (int i = 0; i < properties.Length; i++) myLV.Columns.Add(columns[i]);

            int k = 0;

            foreach (ListViewItem myitem in LV(mylist))
            {
                myLV.Items.Add(myitem);

                k++;
            }
            SetListViewColumnSizes(myLV, -2);
        }

        public void SetListViewColumnSizes(ListView lvw, int width)
        {
            foreach (ColumnHeader col in lvw.Columns)
                col.Width = width;
        }



        public List<t> LoadList<t>(t listItemin, string filename) where t : new()
        {

            PropertyInfo[] properties = listItemin.GetType().GetProperties();
            List<t> mylist = new List<t>();
            Type mytype = listItemin.GetType();

            t listitem;

            listitem = new t();

            string whole_file = System.IO.File.ReadAllText(filename, System.Text.Encoding.GetEncoding("shift_jis"));

            whole_file = whole_file.Replace('\n', '\r');
            string[] lines = whole_file.Split(new char[] { '\r' },
            StringSplitOptions.RemoveEmptyEntries);
            int num_rows = lines.Length;
            int num_cols = properties.Count();

            string[,] values = new string[num_rows, num_cols];

            for (int r = 1; r < num_rows; r++)
            {
                string[] line_r = lines[r].Split(',');

                for (int c = 0; c < num_cols; c++)
                {
                    properties[c].SetValue(listitem, Convert.ChangeType(line_r[c], properties[c].PropertyType, null));
                }

                mylist.Add(listitem);

                listitem = new t();

            }

            return mylist;

        }


    }

    public class SaleData
    {
        public string tenpo { get; set; }
        public int code { get; set; }
        public int rate { get; set; }
        public int quantity { get; set; }
    }

    public class myconvertor
    {
        public filedumprecov mydata = new filedumprecov();
        public List<SaleData> SaleDatas_input;
        public SaleData SaleData_input = new SaleData();
        public List<SaleData> SaleDatas_output;
        public SaleData SaleData_output = new SaleData();

        public SaleData SaleDataView(SaleData input_SD)
        {

            SaleData my_output = new SaleData();

            my_output.tenpo = input_SD.tenpo;
            my_output.code = input_SD.code;
            my_output.rate = input_SD.rate;
            my_output.quantity = input_SD.quantity;

            return my_output;

        }

        public void Caliculate(string my_file)
        {
            SaleDatas_input = mydata.LoadList(SaleData_output, my_file);

            SaleDatas_output = new List<SaleData>();

            foreach(SaleData inpt in SaleDatas_input)
            {
                /*******************************************問題だと思われる個所  (はじめ)******************************************************/

                if(SaleDatas_output.Exists(inpt.tenpo == SaleData_output.tenpo && inpt.code == SaleData_output.code && inpt.rate == SaleData_output.rate))
                {
                    //inpt.quantity += SaleData_output.quantity;
                    //SaleDatas_output.Add(SaleDataView(inpt));
                }
                else
                {
                    SaleDatas_output.Add(SaleDataView(inpt));
                }

                /*****************************************問題だと思われる個所  (終わり)********************************************************/

            }

        }


    }
}

お手数をおかけしてしまい申し訳ございませんが、どなたかお力添えの程頂けないでしょうか。

大変恐縮ですが、よろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

GroupByとSelectでできます
順番までやる場合はOrderByとThenByも必要になります
一応確認済みのソースも張っておきますが、できればご自身でググって色々試しながら身に着けてください

    // 元データ
    var saleDatas = new List<SaleData>();

    //データ追加は省略

    // 出力用データ
    var SaleDatas =
    // グループ化:quantity以外がキー
    saleDatas.GroupBy(x => new { tenpo = x.tenpo, code = x.code, rate = x.rate })
    // quantityのみ合計でそれ以外はキー項目
    .Select(x => new SaleData { tenpo = x.Key.tenpo, code = x.Key.code, rate = x.Key.rate, quantity = x.Sum(y => y.quantity) })
    // 商品コード、店舗名、割引率の順番にソート
    .OrderBy(x=>x.code)
    .ThenBy(x => x.tenpo)
    .ThenBy(x => x.rate);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

ざっとかいてみました。

public void Caliculate(List<SaleData> list)
{
    for(int i=0;i<list.Count;i++){
        for(int k=list.Count-1;k>i;k--){
            if( list[i].tenpo == list[k].tenpo &&
                list[i].code == list[k].code &&
                list[i].rate == list[k].rate
            ){
                // 合算処理
                list[i].quantity += list[k].quantity;
                list.RemoveAt(k);    // 処理済みを削除
            }
        }
    }
}


動かしてませんが、考え方はわかるでしょうか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    7066questions

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