using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
public class Test
{
public static void Main()
{
var candidates = new Dictionary<string, Func<IEnumerable<IEnumerable<int>>, IEnumerable<int>>>
{
{ "Original", Candidates.UOIOriginal<int> },
{ "DoomerOneLine", Candidates.UOIDoomerOneLine<int> },
{ "DoomerSqlLike", Candidates.UOIDoomerSqlLike<int> },
{ "Schmelter", Candidates.UOISchmelter<int> },
{ "Svinja", Candidates.UOISvinja<int> },
{ "Adricadar", Candidates.UOIAdricadar<int> },
};
var testData = new int[][][]
{
new int[][]
{
new[] { 1, 1, 2, 3, 4, 5, 7 },
new[] { 5, 6, 7 },
new[] { 2, 6, 7, 9 },
new[] { 4 }
},
new int[][]
{
new[] { 1, 2, 3 }
},
new int[][]
{
new int[0]
},
new int[][]
{}
};
var validResult = new[] { 2, 4, 5, 6, 7 };
var results = new IEnumerable<int>[1000];
foreach(var pair in candidates)
{
var valid = true;
for (var i = 0; i < testData.Length; i++)
{
if (i == 0)
{
var timer = Stopwatch.StartNew();
valid = pair.Value(testData[i]).OrderBy(d => d).SequenceEqual(validResult);
timer.Stop();
}
else
{
valid = pair.Value(testData[i]).OrderBy(d => d).SequenceEqual(new int[0]);
}
if (!valid)
{
break;
}
}
Console.WriteLine("{0} valid:{1}", pair.Key, valid);
}
foreach(var pair in candidates)
{
var valid = true;
var timer = Stopwatch.StartNew();
for (var i = 0; i < 100000; i++)
{
results[i % 1000] = pair.Value(testData[0]);
}
timer.Stop();
Console.WriteLine("{0} 100000 iterations in {1}ms", pair.Key, timer.ElapsedMilliseconds);
}
}
}
public static class Candidates
{
public static IEnumerable<T> UOIOriginal<T>(
IEnumerable<IEnumerable<T>> source)
{
var pairs =
from s1 in source
from s2 in source
select new { s1 , s2 };
var intersects = pairs
.Where(p => p.s1 != p.s2)
.Select(p => p.s1.Intersect(p.s2));
return intersects.SelectMany(i => i).Distinct();
}
public static IEnumerable<T> UOIDoomerOneLine<T>(
IEnumerable<IEnumerable<T>> source)
{
return source
.SelectMany(e => e.Distinct())
.GroupBy(e => e)
.Where(e => e.Count() > 1)
.Select(e => e.Key);
}
public static IEnumerable<T> UOIDoomerSqlLike<T>(
IEnumerable<IEnumerable<T>> source)
{
return from e in source.SelectMany(e => e.Distinct())
group e by e into g
where g.Count() > 1
orderby g.Key
select g.Key;
}
public static IEnumerable<T> UOISvinja<T>(
IEnumerable<IEnumerable<T>> source)
{
var seenElements = new HashSet<T>();
var repeatedElements = new HashSet<T>();
foreach (var list in source)
{
foreach (var element in list.Distinct())
{
if (seenElements.Contains(element))
{
repeatedElements.Add(element);
}
else
{
seenElements.Add(element);
}
}
}
return repeatedElements;
}
public static IEnumerable<T> UOIAdricadar<T>(
IEnumerable<IEnumerable<T>> source)
{
var result = new List<T>();
var sequences = source.ToList();
for (int sequenceIdx = 0; sequenceIdx < sequences.Count(); sequenceIdx++)
{
var sequence = sequences[sequenceIdx];
for (
int targetSequenceIdx = sequenceIdx + 1;
targetSequenceIdx < sequences.Count;
targetSequenceIdx++)
{
var targetSequence = sequences[targetSequenceIdx];
var intersections = sequence.Intersect(targetSequence);
result.AddRange(intersections);
}
}
return result.Distinct();
}
public static IEnumerable<T> UOISchmelter<T>(
IEnumerable<IEnumerable<T>> source)
{
const int minCount = 2;
var comparer = EqualityComparer<T>.Default;
foreach (T item in source.SelectMany(s => s).Distinct(comparer))
{
int containedInHowManySequences = 0;
foreach (IEnumerable<T> seq in source)
{
bool contained = seq.Contains(item, comparer);
if (contained) containedInHowManySequences++;
if (containedInHowManySequences == minCount)
{
yield return item;
break;
}
}
}
}
}