我有一個列表:計數的重複號碼列表
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