我继承了一个通过JSON访问远程数据的拜占庭API,查询本身是通过TPL处理的,由于我不会进入的原因是支持我进入角落。
所以,我有一个IObservable订阅,我这样查询;
mcSub.Take(1).Subscribe(x => x.Markets.ForEach(i => i.Prices.AvailableToBuy.ForEach(t => tabPanel.textBox1.AppendText(i.Id + " Back \t" + t.Size + " @ " + t.Price))));
显然Markets和AvailableToBuy是列表,我的问题是 - 我如何创建一个LINQ查询/对象来提取i.Id,t.Size和t.Price?
答案 0 :(得分:1)
我相信你可以这样做,在一个集合中扁平两次(一旦市场,然后价格),所有价格:
//get all prices available to buy:
var pricesAvailableToBuy = mcSub.SelectMany(x => x.Markets)
.SelectMany(y => y.Prices.AvailableToBuy)
.Select(p => new { p.Id, p.Size, p.Price });
这为您提供了mcSub
所有市场的所有价格,而您的初始报表仅适用于一个市场项目(这也取决于它的名称 - 如果它是关于消费者工作者的话)任务/线程然后它是有道理的。)
或者,类似的表述:
var pricesAvailableToBuy = mcSub.SelectMany(x => x.Markets.SelectMany(y => y.Prices.AvailableToBuy))
.Select(p => new { p.Id, p.Size, p.Price });
答案 1 :(得分:1)
纬。
这是一个令人讨厌的鸣喇叭订阅/查询blob。让我们看看我们是否可以稍微清理一下......我看到你从mcSub拿到1并订阅它,所以我会假设它是一个可观察的数组?
让我们先假装一些我可以参考的类型(我会尽力从你的样本中推断出来):
首先,数据项:
public class Thing
{
public List<Market> Markets {get; set;}
}
public class Market
{
public Price Prices {get; set;}
}
public class Price
{
public List<AvailablePrice> AvailableToBuy {get; set;}
}
public class AvailablePrice
{
public string Id {get; set;}
public int Size {get; set;}
public decimal Price {get;set;}
}
接下来,会产生IEnumerable<IObservable<Thing>>
的东西,我会一起劈砍:
public IEnumerable<IObservable<Thing>> GetThingsObs()
{
var rnd = new Random();
return Enumerable.Range(0, 3).Select(_ => {
return Observable.Create<Thing>(obs =>
{
var things = Enumerable.Range(0, 3).Select(i => new Thing()
{
Markets = Enumerable.Range(0, 3).Select<int, Market>(x =>
{
return new Market()
{
Prices = new Price
{
AvailableToBuy = Enumerable.Range(0, 3)
.Select(y => new AvailablePrice { Id = string.Format("{0}:{1}:{2}", i, x, y), Size = rnd.Next(0, 10), Price = rnd.Next(0, 20) })
.ToList()
}
};
}).ToList()
});
foreach(var thing in things)
obs.OnNext(thing);
// this bit is important, but I'll get back to it later
obs.OnCompleted();
return Disposable.Empty;
});
});
}
好的,既然我们已经有了某些东西(我希望)有点映射到您的数据,那就让我们来查询吧!
如果已知可观察物完成(我上面的位置被掩盖了),您可以合理安全地将IObservable<T>
转换为IEnumerable<T>
- 如果它不完成,这基本上会挂起,所以要小心!
var mcSub = GetThingsObs();
var query =
// for each observable
from obs in mcSub
// this replaces your subscribe calls, but the observable MUST complete
// for this to return properly!
from thing in obs.ToEnumerable()
// After that, it's just multiple SelectManys
// (which is what the nested 'from x in y' calls get translated into)
// For each market
from market in thing.Markets
// for each price thingy
from price in market.Prices.AvailableToBuy
// select out your stuff
select new { price.Id, price.Size, price.Price };
这是我可以从您提供的样本中做出的最佳猜测 - 如果您可以提供更多信息/详细信息,如果这对您不起作用,我会再拍一次。