另一个程序正在向我的程序传递一个对象列表。这些对象有一个名为Title
的属性,在此列表中,其中一个对象的标题与第一个对象的标题相匹配。我想将此列表分成两个列表,使用与第一个具有相同标题的第二个对象作为标志,将剩余对象写入另一个列表。我写了一个小例子程序,表明我想要完成的事情。我希望那里有人可以指出我正确的方向。
static void Main(string[] args)
{
var names = new string[] {"Frank", "Jules", "Mark", "Allan", "Frank", "Greg", "Tim"};
var listA = new List<string>();
var listB = new List<string>();
foreach (var name in names)
{
// Add all names to listA, until name is the next "Frank".
// If name is the next "Frank" add name and all remaining
// names to listB.
// So, listA would contain "Frank", "Jules", "Mark", "Allan"
// listB would contain "Frank", "Greg", "Tim"
}
}
答案 0 :(得分:6)
这将是我接近它的方式(认为它使用LINQ,你可以不用):
void Main()
{
var names = new string[] {"Frank", "Jules", "Mark", "Allan", "Frank", "Greg", "Tim"};
var listA = new List<string>();
var listB = new List<string>();
// I'm not entirely sure where this comes from other than it's always
// the first element in the "names" list.
var needle = names[0]; // "Frank"
// this finds the location of the second "Frank"
var splitLocation = Array.IndexOf(names, needle, 1);
// here we grab the first elements (up to the splitLocation)
listA = names.Take(splitLocation).ToList();
// here we grab everything past the splitLocation
// (starting with the second "Frank")
listB = names.Skip(splitLocation).ToList();
}
答案 1 :(得分:1)
尝试此算法。
Create a boolean flag with a value of false.
Iterate through the names:
If the current name matches the first name:
Set the flag to true
If the flag is true:
Add the current name to the second list
Else:
Add the current name to the first list
答案 2 :(得分:1)
另一种选择是使用聚合。以下内容将原始集拆分为n集。
var names = new[] { "Frank", "Jules", "Mark", "Allan", "Frank", "Greg", "Tim", "Frank", "Anna" };
string separator = names.First();
var aggregated = names.Aggregate(new List<List<string>>(), (arr, s) =>
{
if (s == separator)
arr.Add(new List<string> { s });
else
arr.Last().Add(s);
return arr;
});
如果你想要严格的1或2套,那么以下代码将起作用:
var names = new[] { "Frank", "Jules", "Mark", "Allan", "Frank", "Greg", "Tim", "Frank", "Anna" };
string separator = names.First();
var aggregated = names.Aggregate(new List<List<string>>(), (arr, s) =>
{
if (s == separator && arr.Count < 2)
arr.Add(new List<string> { s });
else
arr.Last().Add(s);
return arr;
});
var listA = aggregated[0];
var listB = aggregated.Skip(1).FirstOrDefault();
答案 3 :(得分:1)
另一个替代解决方案(对于给定的示例输入)将使用Enumerable.Skip跳过第一个元素,然后使用Enumerable.SkipWhile方法获取第一个列表和List.Remove方法在拆分字后检索第二个列表(TODO:添加异常处理,例如,如果列表为空):
public static class ProjectExtensions
{
public static List<String> SplitTo(this List<String> source, String word)
{
// take first occurrence
var result = new List<String> { source.First() };
// skip already added (first item) and take all until search phrase
result.AddRange(source.Skip(1).TakeWhile (s => s != word));
return result;
}
public static List<String> SkipTo(this List<String> source, String word)
{
var result = source;
// skip all until search phrase and take the rest
result.RemoveRange(0, source.SplitTo(word).Count);
return result;
}
}
用法如下:
var names = new List<String> {"Frank", "Jules", "Mark", "Allan", "Frank", "Greg", "Tim"};
var listA = names.SplitTo("Frank");
var listB = names.SkipTo("Frank");
foreach (var a in listA)
{
Console.WriteLine(a);
}
Console.WriteLine("---------");
foreach (var b in listB)
{
Console.WriteLine(b);
}
输出是:
Frank
Jules
Mark
Allan
---------
Frank
Greg
Tim