首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >连接两个对象优化列表

连接两个对象优化列表
EN

Stack Overflow用户
提问于 2022-04-08 15:31:02
回答 2查看 78关注 0票数 0

我正在寻找优化我的LINQ查询的方法。

课程:

代码语言:javascript
复制
public class OffersObject
{
    public List<SingleFlight> Flights { get; set; }
    public List<Offer> Offers { get; set; } = new List<Offer>();
}

public class SingleFlight
{
    public int Id { get; set; }
    public string CarrierCode { get; set; }
    public string FlightNumber { get; set; }
}

public class Offer
{
    public int ProfileId { get; set; }

    public List<ExtraOffer> ExtraOffers { get; set; } = new List<ExtraOffer>();
}

public class ExtraOffer
{
    public List<int> Flights { get; set; }
    public string Name { get; set; }
}

样本对象:

代码语言:javascript
复制
var sampleObject = new OffersObject
        {
            Flights = new List<SingleFlight>
            {
                new SingleFlight
                {
                    Id = 1,
                    CarrierCode = "KL",
                    FlightNumber = "1"
                },
                new SingleFlight
                {
                    Id = 2,
                    CarrierCode = "KL",
                    FlightNumber = "2"
                }
            },
            Offers = new List<Offer>
            {
                new Offer
                {
                    ProfileId = 41,
                    ExtraOffers = new List<ExtraOffer>
                    {
                        new ExtraOffer
                        {
                            Flights = new List<int>{1},
                            Name = "TEST"
                        },
                        new ExtraOffer
                        {
                            Flights = new List<int>{2},
                            Name = "TEST"
                        },
                        new ExtraOffer
                        {
                            Flights = new List<int>{1,2},
                            Name = "TEST"
                        }
                    }
                }
            }
        };

LINQ查询的目标:

清单:

代码语言:javascript
复制
{ int ProfileId, string CommercialName, List<string> fullFlightNumbers }

FullFlightNumber应该由航班的"Id关联“创建。它创建如下:{CarrierCode} {FlightNumber}

到目前为止,我所拥有的(工作正常,但不是最快的方式):

代码语言:javascript
复制
var result = sampleObject.Offers
                         .SelectMany(x => x.ExtraOffers, 
                                     (a, b) => {
                                                  return new
                                                         {
                                                             ProfileId = a.ProfileId,
                                                             Name = b.Name,
                                                             FullFlightNumbers = b.Flights.Select(f => $"{sampleObject.Flights.FirstOrDefault(fl => fl.Id == f).CarrierCode} {sampleObject.Flights.First(fl => fl.Id == f).FlightNumber}").ToList()
                                                         };
                                            })
                         .ToList();

最后注

在我看来不对的地方是:

代码语言:javascript
复制
.Select(f => $"{sampleObject.Flights.FirstOrDefault(fl => fl.Id == f)?.CarrierCode} {sampleObject.Flights.FirstOrDefault(fl => fl.Id == f)?.FlightNumber}").ToList()

我基本上是在寻找一种方式“加入”这两个名单的OffersObject航班的Id。

任何小费都会得到赏识。

EN

回答 2

Stack Overflow用户

发布于 2022-04-08 20:26:57

如果在sampleObject.Flights中只定义了几个航班,那么使用数字键进行顺序搜索是很难克服的。

但是,如果航班数量比报价次数多(1000 s或更多),我建议将航班列表加载到字典中,并将Id作为有效查找的关键。类似于:

代码语言:javascript
复制
var flightLookup = sampleObject.Flights.ToDictionary(f => f.Id);

然后将FullFlightNumbers计算为

代码语言:javascript
复制
FullFlightNumbers = b.Flights
    .Select(flightId => {
        flightLookup.TryGetValue(flightId, out SingleFlight flight);
        return $"{flight?.CarrierCode} {flight?.FlightNumber}";
    })
    .ToList()

如果找不到匹配,上面的TryGetValue将悄悄地返回一个空值。如果您知道匹配将始终存在,则查找冷将交替编码为:

代码语言:javascript
复制
        SingleFlight flight = flightLookup[flightId];

上面的语句还使用lambda语句。简而言之,lambda函数可以将表达式块或语句块作为主体。有关更多信息,请参见C#参考

票数 0
EN

Stack Overflow用户

发布于 2022-04-09 05:23:29

我建议将双.FirstOrDefault()方法替换为.IntersectBy()。它可以在System.Linq名称空间中使用,从.NET 6开始。

.IntersectBy()基本上通过将sampleObject中的每个航班的航班ID与ExtraOffers.Flights中的航班ID相匹配来过滤ExtraOffers.Flights

在下面的代码中,fl => fl.IdsampleObject.Flights键选择器(即flSingleFlight)。

代码语言:javascript
复制
var result = sampleObject.Offers
    .SelectMany(x => x.ExtraOffers, 
        (a, b) => {
            return new
            {
                ProfileId = a.ProfileId,
                Name = b.Name,
                FullFlightNumbers = sampleObject.Flights
                    .IntersectBy(b.Flights, fl => fl.Id)
                    .Select(fl => fl.FullFlightNumber) // alternative 1
                    //.Select(fl => $"{fl.CarrierCode} {fl.FlightNumber}") // alternative 2
                    .ToList()
            };
        })
    .ToList();

在我的建议中,我将属性FullFlightNumber添加到SingleFlight中,这样Linq语句看起来就稍微干净了一些:

代码语言:javascript
复制
public class SingleFlight
{
    public int Id { get; set; }
    public string CarrierCode { get; set; }
    public string FlightNumber { get; set; }
    
    public string FullFlightNumber => $"{CarrierCode} {FlightNumber}";
}

如果定义SingleFlight.FullFlightNumber对您来说是不可能的/不可取的,则可以使用代码建议中的第二个选项。

例如小提琴这里

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71799656

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档