c#在List中计算连续的重复项
本文关键字:连续 计算 List string | 更新日期: 2023-09-27 18:18:56
我有一个字符串列表,并希望计算其中的重复项,以便稍后使用此信息。简单地计算重复的次数是很容易的,但不幸的是,我只想计算连续的重复次数。
假设我们有一个包含以下字符串items的列表:
"1","3 b","5 x","7问","2 w","2 g","2 j"、"1"、"2"
现在我要计算这个列表中的重复项。我只会看每个字符串的第一个字符,字符串中的其他字符可以忽略!我们得到的是2x"1%"和3x"2%",我实际上想要得到的是连续重复,所以我的结果应该看起来像3x"2%"。2x"1A"必须忽略,它们不是连续的。(% =占位符)
我写了一段代码,循环遍历列表并将一个字符串与下一个字符串进行比较
int counter = 0;
for (int i = 0; i < list.Count; i++)
{
char first = list[i][0];
if ((i + 1) == list.Count) break;
char second = list[(i + 1)][0];
if (first == second)
{
counter++;
}
}
我猜你可以想象这段代码是一种非常丑陋的方式,特别是如果你想要处理输出。我的代码也不能处理我需要的功能。
我要找的代码,必须能够处理我要实现的两个功能。首先,如果列表的最后一个元素等于列表的第一个元素,那么一行重复项就不会结束。
例如:"1","1 b","5 x","7问","2 j","我"
"1%"必须被检测为重复,因为"1I"answers"1A"是"一行"。如果循环遍历列表,如果第一个元素和最后一个元素不相等,则在列表末尾断开。
伪代码:
if(list.First()[0] != list.Last()[0])
我想实现的第二个特性是,列表中不重复的项,"重复计数"超过4的项将被删除。如果没有一个单一的重复行"复制"或长度超过4我想回报。
例如:"1","1 b","5 x","3 q"、"1 j","我"
duplicate count == 4 so return
"1","1 b","1 x","3 q"、"1 j","我"
复制count == 5
,保存这五个项目,删除列表中的任何其他项目。
"1","1 b","1 x","3 q"、"我"、"z 1","1 z"
duplicate count == 6,保存这6项,删除列表中任何其他项。
注意:每个字符串的第一个字符很重要。输入列表将有7个项目,没有一个项目多或少。没有结果列表,旧的需要更新。如果重复计数小于或等于4,则不需要做任何工作,只需返回即可。在一行中不会有超过5个重复。我必须检查十亿的列表,所以性能真的很重要
由于德国学校没有更好的英语教学,我希望任何人都能理解我的问题所在,并愿意帮助我。
这不是任何家庭作业的一部分。
在满足条件的情况下,可以使用一个方法对连续的项进行分组:
public static IEnumerable<IEnumerable<T>> GroupWhile<T>(
this IEnumerable<T> source, Func<T, T, bool> predicate)
{
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
yield break;
List<T> list = new List<T>() { iterator.Current };
T previous = iterator.Current;
while (iterator.MoveNext())
{
if (!predicate(previous, iterator.Current))
{
yield return list;
list = new List<T>();
}
list.Add(iterator.Current);
previous = iterator.Current;
}
yield return list;
}
}
一旦我们有了这个辅助方法,我们就可以用一个相当简单的方式编写查询:
var query = data.GroupWhile((prev, current) => prev[0] == current[0])
.Where(group => group.Count() > 1)
.Select(group => new
{
Character = group.First()[0],
Count = group.Count(),
});
我建议您将列表中以相同字符开头的项分组。这个分组的结果将是一个List<List<string>>
。这使得使用组更容易。
var list = new List<string> {
"1A", "3B", "5X", "7Q", "2W", "2G", "2J", "1B", "1C", "1D", "1E"
};
var groups = new List<List<string>>();
char lastChar = (char)0; // We assume that NUL will never be used as first char.
List<string> group = null;
foreach (string s in list) {
if (s[0] != lastChar) {
group = new List<string>();
groups.Add(group);
lastChar = s[0];
}
group.Add(s);
}
// Join the first and the last group if their first char is equal
int lastIndex = groups.Count - 1;
if (groups.Count > 2 && groups[0][0][0] == groups[lastIndex][0][0]) {
// Insert the elements of the last group to the first group
groups[0].InsertRange(0, groups[lastIndex]);
// and delete the last group
groups.RemoveAt(lastIndex);
}
//TODO: Remove test
foreach (List<string> g in groups) {
Console.WriteLine(g[0][0]);
foreach (string s in g) {
Console.WriteLine(" " + s);
}
}
// Now create a list with items of groups having more than 4 duplicates
var result = new List<string>();
foreach (List<string> g in groups) {
if (g.Count > 4) {
result.AddRange(g);
}
}
//TODO: Remove test
Console.WriteLine("--------");
foreach (string s in result) {
Console.Write(s);
Console.Write(" ");
}
Console.WriteLine();
Console.ReadKey();