8


4

リスト内の重複した数を数える

リストがあります:

int list = { 1,1,2,3,4,4,5,7,7,7,10};

次に、二重の数値を計算するプログラムを作成する必要があります。 前の数字が同じ場合、数字は2倍になります。 理解していただけるといいのですが。 だから、1はダブル、4はダブル、そして7,7,7では2ダブルになりました。

7 Answer


26


LINQのソリューションは次のとおりです。

var doubles = list.Skip(1)
                  .Where((number, index) => list[index] == number);

これは、リストの最初のメンバーをスキップして別のシーケンスを作成し、同じインデックスと同じ値を持つ両方のシーケンスから要素を見つけます。 リストがインデックスによる `O(1)`アクセスを提供するためだけに、線形時間で実行されます。


7


比較的単純で、シーケンスに対して1回だけ反復し、任意のシーケンス(リストだけでなく)で機能するアプローチを次に示します。

public IEnumerable FindConsecutiveDuplicates(this IEnumerable source)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            yield break;
        }
        T current = iterator.Current;
        while (iterator.MoveNext())
        {
            if (EqualityComparer.Default.Equals(current, iterator.Current))
            {
                yield return current;
            }
            current = iterator.Current;
        }
    }
}

これはLINQクエリのみであるという点でさらにシンプルですが、Wh​​ere句で副作用を使用しているため、厄介です。

IEnumerable sequence = ...;

bool first = true;
int current = 0;
var result = sequence.Where(x => {
   bool result = !first && x == current;
   current = x;
   first = false;
   return result;
});

3番目の選択肢は、多少クリーンですが、基本的にhttps://stackoverflow.com/questions/619162/linq-list-of-double-values-differences-between-successor-の SelectPairs`である SelectConsecutive`メソッドを使用します値[この回答]が、少し明確になるように名前が変更されました:)

IEnumerable sequence = ...;
IEnumerable result = sequence.SelectConsecutive((x, y) => new { x, y })
                                  .Where(z => z.x == z.y);


6


誰もがそれを行うための良い方法を見つけようとしているようですので、代わりに本当に悪い方法があります:

List doubles = new List();
Dictionary seenBefore = new Dictionary();

foreach(int i in list)
{
    try
    {
        seenBefore.Add(i, true);
    }
    catch (ArgumentException)
    {
        doubles.Add(i);
    }
}

return doubles;

そんなふうにしないでください。


2


このような何かが動作する可能性があります:

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);


0


ここでは、C#での答えに進みます:)

int[] intarray = new int[] { 1, 1, 2, 3, 4, 4, 5, 7, 7, 7, 10 };

int previousnumber = -1;
List doubleDigits = new List();
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];
    }
}


0


Linqを使用するよりも(おそらく)パフォーマンスが良い例ですが、おそらくエレガントではありません。

for (int i = 1; i < list.Count; i++)
    if (list[i] == list[i - 1])
        doubles.Add(list[i]);


0


あなたはこれをすることができます:

list.GroupBy(i => i).Where(g => g.Count() > 1).SelectMany(g => g.Skip(1))

これは@KJNの答えに少し似ていますが、質問の「doubles」節と「two doubles」節を少し良く表現していると思います。

  1. すべての整数をグループ化します

  2. 複数回現れるものにのみ興味がある( g.Count()> 1

  3. 「ダブル」のフラット化されたリストを選択します。 ( g.Skip(1)

PS:ここでは、 `GroupBy`が最初にリストをソートしないと仮定します。ソートする場合、そのソートは事前にソートされたリストの悪影響を受けません…​