I am stuck with this problem of trying to generate all the variations of K elements from the set [1..N]. I also had an idea that I can do that with k levels of nested loops and tried to do that recursively, but without success.
I have this function:
public static void PrintVariation(int n, int k, int[] array)
{
//when k = 2
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.WriteLine("{0}, {1}", array[i], array[j]);
}
}
}
But what am I supposed to do when k has a random value?
Here is my hint: I think you are on the right track using recursion.
private List<Element[]> getVariations(int k, Element[] elements)
{
// ... ^_^
// use getVariations with less elements in here
}
I'm not sure I follow you though, but this is what I think you should do:
Create a function that will 'generate a variation of K elements from the set [1..N]' It should return that variation.
Call that function in a for-loop in another method that would add it to a generic collection. You may add another routine that would check if the variation generated by the function already exists in the collection and skip adding that variation to the collection.
public static List<List<T>> GetVariations<T>(int k, List<T> elements)
{
List<List<T>> result = new List<List<T>>();
if (k == 1)
{
result.AddRange(elements.Select(element => new List<T>() { element }));
}
else
{
foreach (T element in elements)
{
List<T> subelements = elements.Where(e => !e.Equals(element)).ToList();
List<List<T>> subvariations = GetVariations(k - 1, subelements);
foreach (List<T> subvariation in subvariations)
{
subvariation.Add(element);
result.Add(subvariation);
}
}
}
return result;
}
Related
How would I use the following LINQ query correctly? I want to create a one-dimensional array that contains only values that are greater than 5. I can't understand why it can't iterate over this multidimensional array, but if I use foreach, it actually iterates.
// Create an multidimensional array, then just put numbers into it and print the array.
int[,] myArr = new int[5,6];
int rows = myArr.GetLength(0);
int cols = myArr.GetLength(1);
for (int i = 0; i < rows; i++)
{
for (int k = 0; k < cols; k++)
{
myArr[i,k] = i + k;
Console.Write(myArr[i,k]);
}
Console.WriteLine("");
}
var highList = from val in myArr where (val > 5) select val;
The error is:
Could not find an implementation of the query pattern for source type 'int[*,*]'. 'Where' not found. Are you missing a reference or a using directive for 'System.Linq'?
I thought this might fix the problem:
public static IEnumerator<int> GetEnumerator(int[,] arr)
{
foreach(int i in arr)
{
yield return i;
}
}
But it doesn't implement the iterator.
The problem is that multi-dimensional (rectangular) arrays implement IEnumerable, but not IEnumerable<T>. Fortunately, you can use Cast to fix that - and Cast gets called automatically if you explicitly specify the type of the range variable:
var highList = from int val in myArr where (val > 5) select val;
Or without the unnecessary brackets:
var highList = from int val in myArr where val > 5 select val;
Or using method calls directly, given that it's a pretty trivial query expression:
var highList = myArr.Cast<int>().Where(val => val > 5);
I think this will box each element, however. You could add your own Cast extension method to avoid that:
public static class RectangularArrayExtensions
{
public static IEnumerable<T> Cast<T>(this T[,] source)
{
foreach (T item in source)
{
yield return item;
}
}
}
This is out of curiosity I want to ask this question...
Here is my code:
for (int i = 0; i < myList.Count - 1; ++i)
{
for (int j = i+1; j < myList.Count; ++j)
{
DoMyStuff(myList[i], myList[j]);
}
}
Pretty simple loop, but obviously it only works with List...
But I was wondering... how can I code this loop in order to make it independent of the collection's type (deriving from IEnumerable...)
My first thought:
IEnumerator it1 = myList.GetEnumerator();
while (it1.MoveNext())
{
IEnumerator it2 = it1; // this part is obviously wrong
while (it2.MoveNext())
{
DoMyStuff(it1.Current, it2.Current);
}
}
Because enumerators don't have an efficient way of getting the n'th element, your best bet is to copy the enumerable into a list, then use your existing code:
void CrossMap<T>(IEnumerable<T> enumerable)
{
List<T> myList = enumerable.ToList();
for (int i = 0; i < myList.Count - 1; ++i)
{
for (int j = i+1; j < myList.Count; ++j)
{
DoMyStuff(myList[i], myList[j]);
}
}
}
However, there is a rather tricksie hack you can do with some collection types. Because the enumerators of some of the collection types in the BCL are declared as value types, rather than reference types, you can create an implicit clone of the state of an enumerator by copying it to another variable:
// notice the struct constraint!
void CrossMap<TEnum, T>(TEnum enumerator) where TEnum : struct, IEnumerator<T>
{
while (enumerator.MoveNext())
{
TEnum enum2 = enumerator; // value type, so this makes an implicit clone!
while (enum2.MoveNext())
{
DoMyStuff(enumerator.Current, enum2.Current);
}
}
}
// to use (you have to specify the type args exactly)
List<int> list = Enumerable.Range(0, 10).ToList();
CrossMap<List<int>.Enumerator, int>(list.GetEnumerator());
This is quite obtuse, and quite hard to use, so you should only do this if this is performance and space-critical.
Here is a way that will truly use the lazy IEnumerable paradigm to generate a stream of non-duplicated combinations from a single IEnumerable input. The first pair will return immediately (no cacheing of lists), but there will be increasing delays (still imperceptible except for very high values of n or very expensive IEnumerables) during the Skip(n) operation which occurs after every move forward on the outer enumerator:
public static IEnumerable<Tuple<T, T>> Combinate<T>(this IEnumerable<T> enumerable) {
var outer = enumerable.GetEnumerator();
var n = 1;
while (outer.MoveNext()) {
foreach (var item in enumerable.Skip(n))
yield return Tuple.Create(outer.Current, item);
n++;
}
}
Here is how you would use it in your case:
foreach(var pair in mySource.Combinate())
DoMyStuff(pair.Item1, pair.Item2);
Postscript
Everyone has pointed out (here and elsewhere) that there is no efficient way of getting the "nth" element of an IEnumerable. This is partly because IEnumerable does not require there to even be an underlying source collection. For example, here's a silly little function that that dynamically generates values for an experiment as quickly as they can be consumed, and continues for a specified period of time rather than for any count:
public static IEnumerable<double> Sample(double milliseconds, Func<double> generator) {
var sw = new Stopwatch();
var timeout = TimeSpan.FromMilliseconds(milliseconds);
sw.Start();
while (sw.Elapsed < timeout)
yield return generator();
}
There are extension methods Count() and ElementAt(int) that are declared on IEnumerable<T>. They are declared in the System.Linq namespace, which should be included by default in your .cs files if you are using any C# version later than C# 3. That means that you could you just do:
for (int i = 0; i < myList.Count() - 1; ++i)
{
for (int j = i+1; j < myList.Count(); ++j)
{
DoMyStuff(myList.ElementAt(i), myList.ElementAt(j));
}
}
However, note that these are methods, and will be called over and over again during iteration, so you might want to save their result to variables, like:
var elementCount = myList.Count();
for (int i = 0; i < elementCount - 1; ++i)
{
var iElement = myList.ElementAt(i);
for (int j = i+1; j < elementCount; ++j)
{
DoMyStuff(iElement, myList.ElementAt(j));
}
}
You could also try some LINQ that will select all pair of elements that are eligible, and then use simple foreach to call the processing, something like:
var result = myList.SelectMany((avalue, aindex) =>
myList.Where((bvalue, bindex) => aindex < bindex)
.Select(bvalue => new {First = avalue, Second = bvalue}));
foreach (var item in result)
{
DoMyStuff(item.First, item.Second);
}
I'd write against IEnumerable<T> and pass a delegate for the indexing operation:
public static void DoStuff<T>(IEnumerable<T> seq, Func<int, T> selector)
{
int count = seq.Count();
for (int i = 0; i < count - 1; ++i)
{
for (int j = i+1; j < count; ++j)
{
DoMyStuff(selector(i), selector(j));
}
}
}
You can call it using:
List<T> list = //whatever
DoStuff(list, i => list[i]);
If you restrict the collection argument to ICollection<T> you can use the Count property instead of using the Count() extension method.
Not really efficient, but readable:
int i = 0;
foreach( var item1 in myList)
{
++i;
foreach( var item2 in myList.Skip(i))
DoMyStuff(item1, item2);
}
You can do it fairly succinctly using IEnumerable.Skip(), and it might even be fairly fast compared with copying the list into an array IF the list is short enough. It's bound to be a lot slower than the copying for lists of a sufficient size, though.
You'd have to do some timings with lists of various sizes to see where copying to an array becomes more efficient.
Here's the code. Note that it's iterating an enumerable twice - which will be ok if the enumerable is implemented correctly!
static void test(IEnumerable<int> myList)
{
int n = 0;
foreach (int v1 in myList)
{
foreach (int v2 in myList.Skip(++n))
{
DoMyStuff(v1, v2);
}
}
}
Is there a more elegant way to implement going 5 items at a time than a for loop like this?
var q = Campaign_stats.OrderByDescending(c=>c.Leads).Select(c=>c.PID).Take(23);
var count = q.Count();
for (int i = 0; i < (count/5)+1; i++)
{
q.Skip(i*5).Take(5).Dump();
}
for(int i = 0; i <= count; i+=5)
{
}
So you want to efficiently call Dump() on every 5 items in q.
The solution you have now will re-iterate the IEnumerable<T> every time through the for loop. It may be more efficient to do something like this: (I don't know what your type is so I'm using T)
const int N = 5;
T[] ar = new T[N]; // Temporary array of N items.
int i=0;
foreach(var item in q) { // Just one iterator.
ar[i++] = item; // Store a reference to this item.
if (i == N) { // When we have N items,
ar.Dump(); // dump them,
i = 0; // and reset the array index.
}
}
// Dump the remaining items
if (i > 0) {
ar.Take(i).Dump();
}
This only uses one iterator. Considering your variable is named q, I'm assuming that is short for "query", which implies this is against a database. So using just one iterator may be very beneficial.
I may keep this code, and wrap it up in an extension method. How about "clump"?
public static IEnumerable<IEnumerable<T>> Clump<T>(this IEnumerable<T> items, int clumpSize) {
T[] ar = new T[clumpSize];
int i=0;
foreach(var item in items) {
ar[i++] = item;
if (i == clumpSize) {
yield return ar;
i = 0;
}
}
if (i > 0)
yield return ar.Take(i);
}
Calling it in the context of your code:
foreach (var clump in q.Clump(5)) {
clump.Dump();
}
try iterating by 5 instead!
for(int i = 0; i < count; i += 5)
{
//etc
}
Adding more LINQ with GroupBy and Zip:
q
// add indexes
.Zip(Enumerable.Range(0, Int32.MaxValue),(a,index)=> new {Index=index, Value=a})
.GroupBy(m=>m.Index /5) // divide in groups by 5 items each
.Select(k => {
k.Select(v => v.Value).Dump(); // Perform operation on 5 elements
return k.Key; // return something to satisfy Select.
});
What is best algorithm for removing duplicate values from a list ?
I've tried this:
for (int i = 0; i < AuthorCounter-1; i++)
{
for (int j = 0; j < AuthorCounter-1; j++)
{
if (i != j)
{
if (AuthorGroupNode.Nodes[i].Text == AuthorGroupNode.Nodes[j].Text)
{
AuthorGroupNode.Nodes[j].Remove();
AuthorCounter--;
}
}
}
}
Here, AuthorGroupNodes is a list on nodes. It did things right to some extent, but not perfect. Any one have better solution ???
Your current algorithm is O(N-squared), which will perform quite poorly for a large list.
If space is not an issue, you could keep a HashSet<int> of hashes of nodes. Traverse the list once. If the hash of the node is in the HashSet, you know this is a duplicate node. Skip it. If the hash is not in the HashSet, add this node to a new list, and add the hash of the node to the HashSet.
This will perform O(N), and requires memory for the original list, for a copy of the list less any duplicates, and for the HashSet. The algorithm is non-destructive.
If you can use Linq, simply do
var distinctList = originalList.Distinct().ToList();
UPDATE
Discovered that's pretty much exactly how Jon Skeet re-implemented Distinct.
public static IEnumerable<TSource> Distinct<TSource>(
this IEnumerable<TSource> source)
{
return source.Distinct(EqualityComparer<TSource>.Default);
}
public static IEnumerable<TSource> Distinct<TSource>(
this IEnumerable<TSource> source,
IEqualityComparer<TSource> comparer)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
return DistinctImpl(source, comparer ?? EqualityComparer<TSource>.Default);
}
private static IEnumerable<TSource> DistinctImpl<TSource>(
IEnumerable<TSource> source,
IEqualityComparer<TSource> comparer)
{
HashSet<TSource> seenElements = new HashSet<TSource>(comparer);
foreach (TSource item in source)
{
if (seenElements.Add(item))
{
yield return item;
}
}
}
https://codeblog.jonskeet.uk/2010/12/30/reimplementing-linq-to-objects-part-14-distinct/
This works like a treat:
var xs = new []
{
2, 3, 2, 4, 3, 3, 5, 6,
};
var ys = xs
.ToLookup(z => z, z => z)
.Select(x => x.First());
For your code it would look something like this:
var nodes = AuthorGroupNode.Nodes
.ToLookup(z => z.Text, z => z)
.Select(x => x.First())
.ToArray();
Can't be much simpler than that. :-)
Piggy backing off of Eric J.'s answer... You'll want to implement an EqualityComparer to have complete control over how distinct items are identified.
class Program
{
static void Main(string[] args)
{
var list = new List<SampleClass>();
// add some items
var distinctItems = list.Distinct(new SampleClass());
}
}
public class SampleClass : EqualityComparer<SampleClass>
{
public string Text { get; set; }
public override bool Equals(SampleClass x, SampleClass y)
{
if (x == null || y == null) return false;
return x.Text == y.Text;
}
public override int GetHashCode(SampleClass obj)
{
if (obj == null) return 0;
if (obj.Text == null) return 0;
return obj.Text.GetHashCode();
}
}
more info: http://msdn.microsoft.com/en-us/library/bb338049
You never check the last element of the list, your second for needs to be changed to this to work:
for (int j = 0; j < AuthorCounter; j++)
You are checking each pair of nodes twice. First you'll check when i = 0 and j = 1, then later you'll check when i = 1 and j = 0. There's no need to start j before or equal to i. When i = 0, your inner loop will remove all duplicates of that element so you know AuthorGroupNodes.Nodes[0] is unique. Next time through the outer loop you will be sure that AuthorGroupNodes.Nodes[1] is unique. You can therefore start with j equal to i + 1 and remove your check for i == j. Also when you remove the node, j will still increase to the next node. This will skip the new node at j which is the one after the one you remove, so you should decrement j, or just increment j if you don't remove the node:
for (int j = i + 1; j < AuthorCounter;)
{
if (AuthorGroupNode.Nodes[i].Text == AuthorGroupNode.Nodes[j].Text)
{
AuthorGroupNode.Nodes[j].Remove();
AuthorCounter--;
}
else
{
j++;
}
}
You say that works but not perfect, so I'm assuming you're not using a standard List and that your nodes handle their own removal from the list with the Remove() method.
If the list is sorted by the field you're comparing, you could remove the inner for loop altogether and remove any duplicates of your current element until you find a different one:
for (int i = 0; i < AuthorCounter-1;)
{
if (AuthorGroupNode.Nodes[i].Text == AuthorGroupNode.Nodes[i + 1].Text)
{
AuthorGroupNode.Nodes[i].Remove();
AuthorCounter--;
}
else
{
i++;
}
}
I'm using .NET 3.5 and would like to be able to obtain every *n*th item from a List. I'm not bothered as to whether it's achieved using a lambda expression or LINQ.
Edit
Looks like this question provoked quite a lot of debate (which is a good thing, right?). The main thing I've learnt is that when you think you know every way to do something (even as simple as this), think again!
return list.Where((x, i) => i % nStep == 0);
I know it's "old school," but why not just use a for loop with stepping = n?
Sounds like
IEnumerator<T> GetNth<T>(List<T> list, int n) {
for (int i=0; i<list.Count; i+=n)
yield return list[i]
}
would do the trick. I do not see the need to use Linq or a lambda expressions.
EDIT:
Make it
public static class MyListExtensions {
public static IEnumerable<T> GetNth<T>(this List<T> list, int n) {
for (int i=0; i<list.Count; i+=n)
yield return list[i];
}
}
and you write in a LINQish way
from var element in MyList.GetNth(10) select element;
2nd Edit:
To make it even more LINQish
from var i in Range(0, ((myList.Length-1)/n)+1) select list[n*i];
You can use the Where overload which passes the index along with the element
var everyFourth = list.Where((x,i) => i % 4 == 0);
For Loop
for(int i = 0; i < list.Count; i += n)
//Nth Item..
I think if you provide a linq extension, you should be able to operate on the least specific interface, thus on IEnumerable. Of course, if you are up for speed especially for large N you might provide an overload for indexed access. The latter removes the need of iterating over large amounts of not needed data, and will be much faster than the Where clause. Providing both overloads lets the compiler select the most suitable variant.
public static class LinqExtensions
{
public static IEnumerable<T> GetNth<T>(this IEnumerable<T> list, int n)
{
if (n < 0)
throw new ArgumentOutOfRangeException("n");
if (n > 0)
{
int c = 0;
foreach (var e in list)
{
if (c % n == 0)
yield return e;
c++;
}
}
}
public static IEnumerable<T> GetNth<T>(this IList<T> list, int n)
{
if (n < 0)
throw new ArgumentOutOfRangeException("n");
if (n > 0)
for (int c = 0; c < list.Count; c += n)
yield return list[c];
}
}
I'm not sure if it's possible to do with a LINQ expression, but I know that you can use the Where extension method to do it. For example to get every fifth item:
List<T> list = originalList.Where((t,i) => (i % 5) == 0).ToList();
This will get the first item and every fifth from there. If you want to start at the fifth item instead of the first, you compare with 4 instead of comparing with 0.
Imho no answer is right. All solutions begins from 0. But I want to have the real nth element
public static IEnumerable<T> GetNth<T>(this IList<T> list, int n)
{
for (int i = n - 1; i < list.Count; i += n)
yield return list[i];
}
#belucha I like this, because the client code is very readable and the Compiler chooses the most efficient Implementation. I would build upon this by reducing the requirements to IReadOnlyList<T> and to save the Division for high-performance LINQ:
public static IEnumerable<T> GetNth<T>(this IEnumerable<T> list, int n) {
if (n <= 0) throw new ArgumentOutOfRangeException(nameof(n), n, null);
int i = n;
foreach (var e in list) {
if (++i < n) { //save Division
continue;
}
i = 0;
yield return e;
}
}
public static IEnumerable<T> GetNth<T>(this IReadOnlyList<T> list, int n
, int offset = 0) { //use IReadOnlyList<T>
if (n <= 0) throw new ArgumentOutOfRangeException(nameof(n), n, null);
for (var i = offset; i < list.Count; i += n) {
yield return list[i];
}
}
private static readonly string[] sequence = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15".Split(',');
static void Main(string[] args)
{
var every4thElement = sequence
.Where((p, index) => index % 4 == 0);
foreach (string p in every4thElement)
{
Console.WriteLine("{0}", p);
}
Console.ReadKey();
}
output