【问题标题】:Linq Grouping by a list of a list and selecting from both listsLinq 按列表列表分组并从两个列表中进行选择
【发布时间】:2016-01-06 23:03:14
【问题描述】:

因此,我目前在为 Linq 处理 Group By 时遇到了麻烦,本质上我希望从 Pirate 中获取 id 以及 Ships 中的所有信息,理想情况下将其放入 IEnumerable DataRow 列表中(DataRow 被隐藏了......) .

public class Pirate
    {
        public string Id { get; set; }
        public List<Ship> Ships { get; set; }
    }
    public class Ship
    {
        public string Name { get; set; }
        public string ShipClass { get; set; }
        public string AvastyMast { get; set; }
    }

static void Main(string[] args)
    {
        List<Pirate> Pirates = new List<Program.Pirate>();

        Pirate Arr = new Pirate();
        Arr.Id = "1";

        Ship Pinta = new Ship();
        Pinta.Name = "Maria";
        Pinta.ShipClass = "BattleShip";
        Pinta.AvastyMast = "You Sunk My BattleShip";

        Ship Manta = new Ship();
        Pinta.Name = "Clara";
        Pinta.ShipClass = "Scout";
        Pinta.AvastyMast = "You Sunk My BattleShip!";

        Arr.Ships.Add(Pinta);
        Arr.Ships.Add(Manta);

        Pirates.Add(Arr);

        Pirate Sid = new Pirate();
        Sid.Id = "2";

        Ship Nuclara = new Ship();
        Pinta.Name = "Boon";
        Pinta.ShipClass = "Sub";
        Pinta.AvastyMast = "You Sunk My BattleShip!!";

        Ship Nutella = new Ship();
        Pinta.Name = "Slimer";
        Pinta.ShipClass = "Scout";
        Pinta.AvastyMast = "You Sunk My BattleShip!!!";


    }

所以我想做的是通过上面的 Linq 获得一个 DataRows 列表,这样如果我遍历每个 DataRow 并写出每一行和每一列,它将产生以下内容。

1 , Maria, BattleShip, You Sunk My Battleship
1 , Clara, Scout, You Sunk My Battleship!
2 , Boon, Sub, You Sunk My Battleship!!
2, Slimer, Scout, You Sunk My Battleship!!!

【问题讨论】:

  • 你的问题不是很清楚。什么是输入,什么是预期输出?
  • grab the id from Pirate and all information within Ships, Ideally thrown into a list of IEnumerable. 什么?
  • 您的代码无法编译。 class 是保留关键字。这些是私有领域吗?还是应该是公共财产?
  • 做了一些小的编辑,很抱歉造成混乱,我只是把两个类放在那里作为我正在处理的对象的一个​​例子。将立即进行更多编辑。
  • DataRow 应该包含哪些字段?

标签: c# linq


【解决方案1】:

你可以试试这个:

var pirates = new List<Pirate>(); // or wherever your pirates will come from

var data = from p in pirates
           let pirateId = p.Id
           from s in p.Ships
           select new
           {
               PirateId = pirateId,
               Name = s.Name,
               Class = s.ShipClass,
               AvastyMast = s.AvastyMast
           };

如果你真的想从中取出DataRow 对象,你可以创建一个小方法来创建DataRow

private static DataRow CreateDataRow(DataTable table, string pirateId, string name,
    string shipClass, string avastyMast)
{
    var row = table.NewRow();

    // Make sure the column names match those in the table!
    row["PirateId"] = pirateId;
    row["Name"] = name;
    row["ShipClass"] = shipClass;
    row["AvastyMast"] = avastyMast;

    return row;
}

并像这样使用它:

var pirates = new List<Pirate>(); // or wherever your pirates will come from
var dataTable = new DataTable(); // or wherever your DataTable will come from

var data = from p in pirates
           let pirateId = p.Id
           from s in p.Ships
           select CreateDataRow(dataTable , pirateId, s.Name, s.ShipClass, s.AvastyMast);

【讨论】:

  • 是的,假设他并不真正需要数据行,这个是有意义的。
  • 问题是它来自海盗名单(我的错是最初的问题格式错误)。
  • @IvanS 为什么这是个问题?查询将在pirates 中工作,是Pirate 对象的集合。
  • 你们是 100% 正确的,因为我在第二次使用海盗而不是 p 时感到困惑,并且无法访问船只。将验证一两件事,但可能会将其标记为答案。
  • 是的,这行得通,(也意识到我的现实生活中的例子有另一个列表可以从中获取数据......)但应用了相同的结果,它似乎工作正常..本质上我只是添加了另一个从中汲取灵感,虽然现在我有点偏执..
【解决方案2】:

试试这个

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Pirate> pirates = new List<Pirate>() {
                    new Pirate() { id = "1" , Ships = new List<Ship>(){
                        new Ship() { name = "Maria", _class = "BattleShip", avastyemast = "You Sunk My Battleship"},
                        new Ship() { name = "Clara", _class = "Scout", avastyemast = "You Sunk My Battleship"}
                    }
                },
                    new Pirate() { id = "2" , Ships =  new List<Ship>() {
                        new Ship() { name = "Boon", _class = "Sub", avastyemast = "You Sunk My Battleship"},
                        new Ship() { name = "Slimer", _class = "Scout", avastyemast = "You Sunk My Battleship"}
                    }
                }
            };

            DataTable dt = new DataTable();
            dt.Columns.Add("id", typeof(string));
            dt.Columns.Add("name", typeof(string));
            dt.Columns.Add("class", typeof(string));
            dt.Columns.Add("avastyemast", typeof(string));

            foreach (Pirate pirate in pirates)
            {
                foreach(Ship ship in pirate.Ships)
                {
                    dt.Rows.Add(new string[] {
                        pirate.id,
                        ship.name,
                        ship._class,
                        ship.avastyemast
                    });
                }

            }


            //using linq
           var newRows = pirates.Select(x => x.Ships.Select(y => new List<object>() {x.id, y.name, y._class, y.avastyemast})).SelectMany(z => z).ToList();
           foreach (var row in newRows)
           {
               dt.Rows.Add(row);
           }
        }
    }
    public class Pirate
    {
        public string id {get;set;} 
        public List<Ship> Ships {get;set;}

    }
    public class Ship
    {
        public string name {get;set;}
        public string _class {get;set;}
        public string avastyemast {get;set;}
    }
}
​

【讨论】:

  • 这种方式很有效,并且主要是我想到的原始方式,尽管我觉得使用 Linq 可能更有效。不过,感谢您为我的备份计划提供更优化的版本。
  • 将您的数据添加到示例中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-01
相关资源
最近更新 更多