Select 匹配数组中的字段和 C# Linq 的父项

Select fields in a matching array and parent with C# Linq

我有一个对象,我需要从第一个匹配的字段中获取一些字段。关键是“价格”将按升序或降序“基本”顺序排序。找到第一个匹配的“base”并确保“availability.amount”符合条件,最后 return“base”、“priceTypeID”和“priceLevelID”。这是一小段代码,它不能满足我的需要;基本上,一个结果给了我 3 个匹配项,而另一个没有给我“priceLevelID”。

我下面的标准应该 return "base"=4000, "priceTypeID"="45082" and "priceLevelID"="2650"


public class PriceInfo
{
    public class Availability
    {
        public int amount { get; set; }
    }

    public class Price
    {
        public int @base { get; set; }
        public string priceTypeID { get; set; }
    }

    public class PriceLevel
    {
        public string priceLevelID { get; set; }
        public Availability availability { get; set; }
        public List<Price> prices { get; set; }
    }

    public class ZonePrice
    {
        public List<PriceLevel> priceLevels { get; set; }
    }

    public class OfferPrice
    {
        public List<ZonePrice> zonePrices { get; set; }
    }

    public class RootObject
    {
        public List<OfferPrice> offerPrices { get; set; }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var json = @"{
            ""offerPrices"": [
                {
                    ""zonePrices"": [
                        {
                            ""priceLevels"": [
                                {
                                    ""priceLevelID"": ""1653"",
                                    ""availability"": {
                                        ""amount"": 296
                                    },
                                    ""prices"": [
                                        {
                                            ""base"": 2000,
                                            ""priceTypeID"": ""45082""
                                        }
                                    ]
                                },
                                {
                                    ""priceLevelID"": ""1029"",
                                    ""availability"": {
                                        ""amount"": 300
                                    },
                                    ""prices"": [
                                        {
                                            ""base"": 3000,
                                            ""priceTypeID"": ""45082""
                                        }
                                    ]
                                },
                                {
                                    ""priceLevelID"": ""2650"",
                                    ""availability"": {
                                        ""amount"": 400
                                    },
                                    ""prices"": [
                                        {
                                            ""base"": 4000,
                                            ""priceTypeID"": ""45082""
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }";

        var obj = JsonConvert.DeserializeObject<PriceInfo.RootObject>(json);

        var queryResult1 = obj.offerPrices[0].zonePrices[0].priceLevels.Where(w => w.availability.amount >= 2 &&
                                w.prices.OrderByDescending(o => o.@base).Any(w2 => w2.@base > 1000 && w2.@base < 300000)).FirstOrDefault();

        var queryResult2 = obj.offerPrices[0].zonePrices[0].priceLevels.Select(o => new { o.prices, o.priceLevelID, o.availability.amount }).
                                Select(o2 => o2.prices.OrderByDescending(o3 => o3).Where(w => w.@base > 1000 && w.@base < 300000).
                                Select(s => new { o2.priceLevelID, s.priceTypeID, s.@base, o2.amount }).First()).
                                Where(w2 => w2.amount > 2).First();

我不清楚你的 selection 标准是什么,但我是这样考虑这个查询的。

首先,select 叶节点,因为您根据它们进行过滤。在这里,我根据您的示例查询做出关于订购的假设:

var ordered = obj.offerPrices
  .SelectMany(o => o.zonePrices)
  .SelectMany(z => z.priceLevels)
  .Select(l => new 
  {
    comparisonPrice = l.prices.MaxBy(p => p.@base).First(), // MaxBy from morelinq. Requires First() because there can be multiple equal base prices
    l.priceLevelID,
    l.availability
  })
  .OrderByDescending(l => l.comparisonPrice.@base);

接下来,筛选出所需价格范围内的结果:

var minBase = 1000;
var maxBase = 300000;

var meetsPriceRange = ordered
    .Where(o => o.comparisonPrice.@base > minBase && 
                o.comparisonPrice.@base < maxBase);

最后,确保所需的最低可用性并选出我们的获胜者:

var minAvailable = 2;
var meetsMinimumAmount = ordered
  .Where(o => o.availability.amount >= minAvailable)
  .Select(o => new {
    o.comparisonPrice.@base,
    o.comparisonPrice.priceTypeID,
    o.priceLevelID
  })
  .First();

输出:

base: 4000
priceTypeId: 45082
priceLevelID: 2650

试试这个

var basePriceItem = obj.offerPrices.SelectMany(o => o.zonePrices)
.SelectMany(z => z.priceLevels).SelectMany(s => s.prices).OrderByDescending(o => o.@base)
.FirstOrDefault(b => b.@base > 1000 && b.@base < 300000);

var item = obj.offerPrices.SelectMany(o => o.zonePrices)
.SelectMany(z => z.priceLevels)
.FirstOrDefault(o => o.prices.Any(p => p.priceTypeID == basePriceItem.priceTypeID && p.@base == basePriceItem.@base));

输出

{
  "priceLevelID": "2650",
  "availability": {
    "amount": 400
  },
  "prices": [
    {
      "base": 4000,
      "priceTypeID": "45082"
    }
  ]
}

我觉得你是在问这个:

    var query =
        from x in obj.offerPrices[0].zonePrices[0].priceLevels
        where x.availability.amount > 2
        from y in x.prices
        where y.@base > 1000
        where y.@base < 300000
        orderby y.@base descending
        select new { x.priceLevelID, y.priceTypeID, y.@base, x.availability.amount };
        
    var result = query.FirstOrDefault();

这给了我:


    var query =
        obj
            .offerPrices[0]
            .zonePrices[0]
            .priceLevels
            .Where(x => x.availability.amount > 2)
            .SelectMany(x =>
                x
                    .prices
                    .Where(y => y.@base > 1000)
                    .Where(y => y.@base < 300000)
                    .OrderByDescending(y => y.@base),
                (x, y) => new { x.priceLevelID, y.priceTypeID, y.@base, x.availability.amount });