这是一个类的IEnumerable。
IEnumerable<Card> cardList = new List<Card> {
new Card { CardNumber = 1234, Amount = 10m, DisplayText = "" },
new Card { CardNumber = 1235, Amount = 10m, DisplayText = "" },
new Card { CardNumber = 1236, Amount = 10m, DisplayText = "" },
new Card { CardNumber = 1237, Amount = 10m, DisplayText = "" },
new Card { CardNumber = 1238, Amount = 10m, DisplayText = "" },
new Card { CardNumber = 1239, Amount = 15m, DisplayText = "" },
new Card { CardNumber = 1240, Amount = 10m, DisplayText = "" },
new Card { CardNumber = 1241, Amount = 10m, DisplayText = "" },
new Card { CardNumber = 1242, Amount = 25m, DisplayText = "" },
new Card { CardNumber = 1243, Amount = 25m, DisplayText = "" },
new Card { CardNumber = 1244, Amount = 25m, DisplayText = "" },
new Card { CardNumber = 1245, Amount = 25m, DisplayText = "" }
};
我想要完成的是按数量和顺序卡片号对列表进行分组,而组中至少有4张卡,否则就不会分组。这是我想要达到的目标的一个例子。结果将是另一个IEnumerable,并包含以下内容
Card { CardNumber = null, Amount = 10m, DisplayText = "1234 - 1238" },
Card { CardNumber = null, Amount = 15m, DisplayText = "1239" },
Card { CardNumber = null, Amount = 10m, DisplayText = "1240" },
Card { CardNumber = null, Amount = 10m, DisplayText = "1241" },
Card { CardNumber = null, Amount = 25m, DisplayText = "1242 - 1245" }
希望我能做到这一点。任何帮助都将不胜感激。
谢谢,
发布于 2017-01-16 20:10:04
纯LINQ运算符是不可能的。但是,可以使用混合标准和自定义LINQ类扩展方法。
让我们创建一个自定义方法,该方法允许我们根据接收、先前和当前元素的谓词拆分序列:
public static class Extensions
{
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, Func<T, T, bool> splitOn)
{
using (var e = source.GetEnumerator())
{
for (bool more = e.MoveNext(); more; )
{
var last = e.Current;
var group = new List<T> { last };
while ((more = e.MoveNext()) && !splitOn(last, e.Current))
group.Add(last = e.Current);
yield return group;
}
}
}
}
现在您可以使用以下查询来完成您的目标:
var result = cardList.OrderBy(c => c.CardNumber)
.Split((prev, next) => prev.Amount != next.Amount || prev.CardNumber + 1 != next.CardNumber)
.SelectMany(g => g.Count() >= 4 ?
new [] { new Card { Amount = g.First().Amount, DisplayText = g.First().CardNumber + " - " + g.Last().CardNumber } } :
g.Select(c => new Card { Amount = c.Amount, DisplayText = c.CardNumber.ToString() }));
OrderBy
后面跟着自定义Split
进行初始分组。剩下的棘手部分是如何基于Count
标准对组/取消组元素进行分组,这是通过在一种情况下生成单个项(通过选择单个项数组)的条件SelectMany
方法实现的,或者是通过使用内部Select
在另一种情况下扁平组来实现的。
发布于 2017-01-16 19:37:41
我不认为这样的事情可以用LINQ来完成。
但是如果没有LINQ,这是很容易实现的,比如:(我假设cardList
是由CardNumber
命令的)
List<Card> result = new List<Card>();
Func<List<Card>,List<Card>> bufferToResult = (buf) =>
{
List<Card> res = new List<Card>();
if(buf.Count >= 4) {
string text = buf[0].CardNumber + " - " + buf[buf.Count-1].CardNumber;
Card newCard = new Card { Amount = buf[0].Amount, DisplayText = text };
res.Add(newCard);
} else {
foreach(Card c in buf) {
Card newCard = new Card { Amount = c.Amount, DisplayText = c.CardNumber.ToString() };
res.Add(newCard);
}
}
return res;
};
List<Card> buffer = new List<Card>();
for(int i=0; i<cardList.Count(); ) {
Card card = cardList.ElementAt(i);
if(buffer.Count == 0) {
buffer.Add(card);
i++;
} else if(card.Amount == buffer[0].Amount) {
buffer.Add(card);
i++;
} else {
result.AddRange(bufferToResult(buffer));
buffer.Clear();
}
}
if(buffer.Count > 0)
result.AddRange(bufferToResult(buffer));
发布于 2017-01-16 20:57:58
您可以通过将通过约束进行的项分组到一个新列表中,然后根据组大小填充第二个列表来实现这一点:
IList<Card> group = new List<Card>();
IList<Card> result = new List<Card>();
for (int i = 0, j = 0; i < cardList.Count - 1; i++)
{
group.Clear();
group.Add(cardList[i]);
for (j = i + 1; j < cardList.Count; j++, i++)
{
if (cardList[j].Amount == cardList[i].Amount && cardList[j].CardNumber - cardList[i].CardNumber == 1)
{
group.Add(cardList[j]);
}
else break;
}
if (4 > group.Count)
{
foreach (var item in group)
{
result.Add(new Card { Amount = item.Amount, DisplayText = item.CardNumber.ToString() });
}
}
else
{
result.Add(new Card { Amount = group[0].Amount, DisplayText = string.Format("{0} - {1}", group[0].CardNumber, group.Last().CardNumber) });
}
}
使用LINQPad的结果:
CardNumber Amount DisplayText
null 10 1234 - 1238
null 15 1239
null 10 1240
null 10 1241
null 25 1242 - 1245
比起过于复杂的Linq代码,我更喜欢这个。
https://stackoverflow.com/questions/41683387
复制相似问题