按元素划分子列表中的列表
本文关键字:列表 元素 划分 | 更新日期: 2023-09-27 18:17:57
我有一个字符串列表:
{"foo", "str1", "str2", ..., "bar", ..., "baz", ...}
我需要得到"foo"
, "bar"
和"baz"
之间字符串的子列表。
可以用linq来做这个吗?
编辑
您可以这样做来区分任意两个元素之间的所有元素:
var strings = new[] { "foo", "str1", "str2", ... "bar", ... "baz" };
var between = strings.SkipWhile(s => s != "foo").Skip(1)
.TakeWhile(s => s != "bar"); // "str1", "str2", ...
如果你想获得"foo"answers"baz"之间的所有内容,除了"bar",使用这个(假设顺序为"foo", "bar", "baz"):
var strings = new[] { "foo", "str1", "str2", ... "bar", ... "baz" };
var between = strings.SkipWhile(s => s != "foo").Skip(1)
.TakeWhile(s => s != "baz")
.Where(s => s != "bar"); // "str1", "str2", ...
或者如果你愿意使用有副作用的Linq查询,你可以这样做,通过某些'stop'词来划分你的输入列表:
var stops = new[] { "foo", "bar", "baz" };
var strings = new[] { "foo", "str1", "str2", "bar", "str3", "baz" };
var p = -1;
var partitions =
from s in strings
let i = Array.IndexOf(stops, s)
group s by p = i == -1 ? p : i into g
where g.Key == 0 || g.Key == 1
select g.Skip(1); // { "str1", "str2" }, { "str3" }
或者更有效率一点(因为它在第三个停止字之后停止处理):
var partitions =
(from s in strings
let i = Array.IndexOf(stops, s)
group s by p = i == -1 ? p : i)
.SkipWhile(g => g.Key < 0)
.Take(2)
.Select(g => g.Skip(1)); // { "str1", "str2" }, { "str3" }
现在,这个方法有点粗糙,当涉及到"foo"之前或"baz"之后的项目时,它有点繁琐,但如果你只寻找"foo"answers"baz"之间的项目,它应该为你工作。它还有一个额外的好处,即停止词的顺序不会影响结果。
var idxFoo = list.IndexOf("foo");
var idxBar = list.IndexOf("bar");
var idxBaz = list.IndexOf("baz");
var subList1 = list.Skip(idxFoo).Take(idxBar - idxFoo);
var subList2 = list.Skip(idxBar).Take(idxBaz - idxBar);
如果你只想在你的扩展数据列表中迭代一次,你可以这样做:
List<string> longDataList = new List<string> { "foo", "str1", "str2", "str1", "str2", "str1", "str2", "bar", "str1", "str2", "str1", "str2", "str1", "str2", "baz", "str1", "str2", "str1", "str2", "str1", "str2" };
List<string> splitters = new List<string> { "foo", "bar", "baz" };
Dictionary<string, List<string>> resultDict = new Dictionary<string, List<string>>();
List<string> currentList = null;
longDataList.ForEach(s =>
{
if (splitters.Contains(s))
{
if (resultDict.ContainsKey(s))
currentList = resultDict[s];
else
{
currentList = new List<string>();
resultDict.Add(s, currentList);
}
}
else
currentList.Add(s);
});
至少使用了一点linq,但在您的扩展数据列表中只迭代一次。