我有一个列表:计数的重复号码列表
int list = { 1,1,2,3,4,4,5,7,7,7,10};
现在我需要做一个程序,计算出双号。当它之前的数字相同时,数字是双倍的。我希望你明白。所以1是双倍,4是双打,我们在7,7,7中得到2双。
我有一个列表:计数的重复号码列表
int list = { 1,1,2,3,4,4,5,7,7,7,10};
现在我需要做一个程序,计算出双号。当它之前的数字相同时,数字是双倍的。我希望你明白。所以1是双倍,4是双打,我们在7,7,7中得到2双。
下面是LINQ的溶液:
var doubles = list.Skip(1)
.Where((number, index) => list[index] == number);
这通过跳过列表的第一个成员创建另一序列,然后发现从具有相同索引和相同的值两个序列元件。它将以线性时间运行,但只是因为列表按索引提供了O(1)
访问权限。
这样的事情可能工作:
list.GroupBy (l => l).Where (l => l.Count() > 1).SelectMany (l => l).Distinct();
编辑:
上面的代码中并没有得到结果的OP通缉。下面是经编辑的版本,在下面,其灵感来自安仁的优雅的解决方案::)
list.GroupBy(l => l).Select(g=>g.Skip(1)).SelectMany (l => l);
这里有一个方法是比较简单,只迭代一次在序列,并与任何序列作品(不只是列出):
public IEnumerable<T> FindConsecutiveDuplicates<T>(this IEnumerable<T> source)
{
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
yield break;
}
T current = iterator.Current;
while (iterator.MoveNext())
{
if (EqualityComparer<T>.Default.Equals(current, iterator.Current))
{
yield return current;
}
current = iterator.Current;
}
}
}
这里是另外一个是即使在它只是一个LINQ查询简单,但它使用Where子句,这是讨厌的副作用:
IEnumerable<int> sequence = ...;
bool first = true;
int current = 0;
var result = sequence.Where(x => {
bool result = !first && x == current;
current = x;
first = false;
return result;
});
第三种选择,这是有点清洁,但使用SelectConsecutive
方法基本上是从SelectPairs
this answer,但改名为稍微清晰的:)
IEnumerable<int> sequence = ...;
IEnumerable<int> result = sequence.SelectConsecutive((x, y) => new { x, y })
.Where(z => z.x == z.y);
你是什么意思“使用副作用”? – 2010-10-01 13:11:45
我的眼睛在流血。 – 2010-10-01 13:16:21
@Lasse:好点。呃,我改变了我的计划。等一下,我会把副作用的版本备份:) – 2010-10-01 13:16:38
每个人似乎都试图找到这样做的好方法,所以这是一个非常糟糕的方式,而不是:
List<int> doubles = new List<int>();
Dictionary<int, bool> seenBefore = new Dictionary<int, bool>();
foreach(int i in list)
{
try
{
seenBefore.Add(i, true);
}
catch (ArgumentException)
{
doubles.Add(i);
}
}
return doubles;
请不要这样做。
哈哈,幽默感+1。这是星期五毕竟 – 2010-10-01 13:24:44
谢谢。我不确定是否因为发布错误答案而得票低,或者因为发表不合格而赞成票。 :-) – teedyay 2010-10-01 13:38:32
+1除了异常之外,它并不是一个完全不好的非Linq答案 - 你可以使用ContainsKey或TryGetValue来避免异常,它会很好。 – 2010-10-01 13:50:28
在这里,你的答案去在C#:)
int[] intarray = new int[] { 1, 1, 2, 3, 4, 4, 5, 7, 7, 7, 10 };
int previousnumber = -1;
List<int> doubleDigits = new List<int>();
for (int i = 0; i < intarray.Length; i++)
{
if (previousnumber == -1) { previousnumber = intarray[i]; continue; }
if (intarray[i] == previousnumber)
{
if (!doubleDigits.Contains(intarray[i]))
{
doubleDigits.Add(intarray[i]);
//Console.WriteLine("Duplicate int found - " + intarray[i]);
continue;
}
}
else
{
previousnumber = intarray[i];
}
}
是(可能)的性能比使用LINQ更好,虽然一个例子可以说是那么优雅:
for (int i = 1; i < list.Count; i++)
if (list[i] == list[i - 1])
doubles.Add(list[i]);
你可以这样做:
list.GroupBy(i => i).Where(g => g.Count() > 1).SelectMany(g => g.Skip(1))
这有点像@ KJN的回答,除了我认为它表达了“双打”和“双打”条款在这个问题好一点:
g.Count() > 1
)g.Skip(1)
)PS:我们这里假设,即GroupBy
不先排序列表,如果是的话,那那种没有负面的预排序列表的影响...
你可以提供更多的信息,为什么/如何?感觉像一个家庭作业/面试问题。如果找到匹配,只需使用一个循环来解决并比较之前的当前和存储/重置将是非常简单的 - 只是一些额外的逻辑来停止7被计数3次。如果你想用linq或其他东西来解决它,那就更有趣了。 – 2010-10-01 13:06:31