This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Lists permutations (unknown number)
Lets say I have input of Range[1, 8]
{1,2,3,4,5,6,7,8}
and i want to find Subsets[%, {2}] (all subsets with exact length of 2)
{{1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}, {2, 3}, {2, 4},
{2, 5}, {2, 6}, {2, 7}, {2, 8}, {3, 4}, {3, 5}, {3, 6}, {3, 7}, {3, 8},
{4, 5}, {4, 6}, {4, 7}, {4, 8}, {5, 6}, {5, 7}, {5, 8}, {6, 7}, {6, 8}, {7, 8}}
Tried:
var values = Enumerable.Range(1, 8);
var result = from v in values
from v2 in values.Skip(v)
select new[] { v, v2 };
Here is a function to find all combinations of an input sequence of a specified size:
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> source, int n)
{
if (n == 0)
yield return Enumerable.Empty<T>();
int count = 1;
foreach (T item in source)
{
foreach (var innerSequence in source.Skip(count).Combinations(n - 1))
{
yield return new T[] { item }.Concat(innerSequence);
}
count++;
}
}
So in your case you'd use it as:
var result = Enumerable.Range(1, 8).Combinations(2);
var query = from a in Enumerable.Range(1, 8)
from b in Enumerable.Range(a + 1, 8 - a)
select String.Format("{{{0}, {1}}}", a, b);
foreach (string s in query)
{
Console.Out.WriteLine(s);
}
var lst = Enumerable.Range(1, 8);
var result = lst.Join(lst, c => 1, c => 1, (i, j) => new[] { i, j })
.Where(c => c[0] < c[1]);
Here I used the condition 1 == 1 to get the cross join of values in Enumerable.Range(1, 8) to get all possible combinations.
As noted in comments probably an easier way to generate a cross join is by:
var result = lst.SelectMany(_ => lst, (i, j) => new[] { i, j })
.Where(c => c[0] < c[1]);
but is less readable to my eyes.
Please note that this is little less efficient compared to other methods as this first gets all the possible combinations and then trim down the unwanted. Nevertheless a simple one-liner.
Related
How do you iterate through a 2d array and get the first element in each row? For example:
int[,] array = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
desired output: 1 4 7 10
Something like this should do the trick:
int[,] array = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
for (int row = 0; row < array.GetLength(0); ++row)
{
Console.WriteLine(array[row, 0]);
}
Try it online
I searched, but I found only answers which related to two lists. But what about when they are more than two?
List 1 = 1,2,3,4,5
List 2 = 6,7,8,9,1
List 3 = 3,6,9,2,0,1
List 4 = 1,2,9,0,5
List 5 = 1,7,8,6,5,4
List 6 = 1
List 7 =
How to get the common items? as you can see one of them is empty, so the common will be empty, but I need to skip empty lists.
var data = new List<List<int>> {
new List<int> {1, 2, 3, 4, 5},
new List<int> {6, 7, 2, 8, 9, 1},
new List<int> {3, 6, 9, 2, 0, 1},
new List<int> {1, 2, 9, 0, 5},
new List<int> {1, 7, 8, 6, 2, 5, 4},
new List<int> {1, 7, 2}
};
List<int> res = data
.Aggregate<IEnumerable<int>>((a, b) => a.Intersect(b))
.ToList();
The type of Aggregate is explicitly given, otherwise aggregation of two Lists would have to be List too. It can be easily adapted to run in parallel:
List<int> res = data
.AsParallel<IEnumerable<int>>()
.Aggregate((a, b) => a.Intersect(b))
.ToList();
EDIT
Except... it does not run in parallel. The problem is operations on IEnumerable are deferred, so even if they are logically merged in parallel context, the actual merging occurs in the ToList(), which is single threaded. For parallel execution it would be better to leave IEnumerable and return to the Lists:
List<int> res = data
.AsParallel()
.Aggregate((a, b) => a.Intersect(b).ToList());
You can chain Intersect:
List<int> List1 = new List<int> {1, 2, 3, 4, 5};
List<int> List2 = new List<int> { 6, 7, 8, 9, 1 };
List<int> List3 = new List<int> { 3, 6, 9, 2, 0, 1 };
List<int> List4 = new List<int> { 1, 2, 9, 0, 5 };
List<int> List5 = new List<int> { 1, 7, 8, 6, 5, 4 };
List<int> List6 = new List<int> { 1 };
List<int> common = List1
.Intersect(List2)
.Intersect(List3)
.Intersect(List4)
.Intersect(List5)
.Intersect(List6)
.ToList();
var data = new [] {
new List<int> {1, 2, 3, 4, 5},
new List<int> {6, 7, 8, 9, 1},
new List<int> {3, 6, 9, 2, 0, 1},
new List<int> {1, 2, 9, 0, 5},
new List<int> {1, 7, 8, 6, 5, 4},
new List<int> {1},
new List<int> {},
null
};
IEnumerable<int> temp = null;
foreach (var arr in data)
if (arr != null && arr.Count != 0)
temp = temp == null ? arr : arr.Intersect(temp);
One way is to use a HashSet. You can put the items of the first collection in the hash, then iterate each collection after the first and create an new hash that you add items from the current collection to if it's in the hash. At the end you assign that common hash set to the overall one and break if it's every empty. At the end you just return the overall hash set.
public IEnumerable<T> CommonItems<T>(IEnumerable<IEnumerable<T>> collections)
{
if(collections == null)
throw new ArgumentNullException(nameof(collections));
using(var enumerator = collections.GetEnumerator())
{
if(!enumerator.MoveNext())
return Enumerable<T>.Empty();
var overall = new HashSet<T>(enumerator.Current);
while(enumerator.MoveNext())
{
var common = new HashSet<T>();
foreach(var item in enumerator.Current)
{
if(hash.Contains(item))
common.Add(item);
}
overall = common;
if(overall.Count == 0)
break;
}
return overall;
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
How I can get ordered pairs of elements from some array, using LINQ? For example,
I have:
int[] d = { 1, 2, 3 };
I need:
{ {1, 1}, {1, 2}, ...., {3, 3} }
I tried that LINQ query, but it returns
{ {1, 1}, {2, 2}, {3, 3}, {1, 1}, {2, 2}, {3, 3}, {1, 1}, {2, 2}, {3,
3} }
var pairs = d.SelectMany(a => d.Select(b => new[] { a, b }));
Please, help me to find my error.
Like this:
var result = d.SelectMany(a => d, Tuple.Create)
.Where(c=> c.Item1 <= c.Item2).ToArray();
this code work
int[] d = { 1, 2, 3 };
var query = (from elem1 in d
from elem2 in d
where elem1>= elem2
select elem1< elem2? new List<int>() { elem1, elem2 }: new List<int>() { elem2, elem1 }
).Distinct().ToArray();
In python there is a functionality (numpy.take) to sort arrays within an array, for example if I have an array (3x3):
a = [[1, 2, 3],[7,9,10],[3, 5,6]]
and I have an array of set indices
indices = [2, 0, 1]
the result shall be
array([[ 3, 5, 6], [ 1, 2, 3], [ 7, 9, 10]]).
Are there any direct approach methods/ functions as these in C# where I can pass in a jagged array and produce the same output?
Not directly, but you can achieve the same thing with Linq
var a = new[] { new[] { 1, 2, 3 }, new[] { 7, 9, 10 }, new[] { 3, 5, 6 } };
var indices = new [] { 2, 0, 1 };
var sorted = indices.Select(i => a[i]).ToArray();
foreach(var s in sorted) Console.WriteLine(string.Join(", ", s));
Note this does not check that your indices are all in range.
You can do it easily with LINQ:
var a = new[] { new[] { 1, 2, 3 }, new[] { 7, 9, 10 }, new[] { 3, 5, 6 } };
var indices = new[] { 2, 0, 1};
var result = indices
.Select(i => a[i])
.ToArray();
Or .ToList() if you prefer lists.
There is also the Array.Sort(keys, values) - MSDN
var a = new[]
{
new[] {1, 2, 3},
new[] {7, 9, 10},
new[] {3, 5, 6}
};
var indices = new[] {2, 0, 1};
var sortedArray = a.SortEx(indices);
Where SortEx is
public static class Extensions
{
public static T[][] SortEx<T>(this T[][] source, int[] indices)
{
return indices.Select(index => source[index]).ToArray();
}
}
This assumes that the all the indices in the indices array are not out of bound in a.
Consider the following structure:
IEnumerable<IEnumerable<int>> collection = new[] {
new [] {1, 2, 3},
new [] {4, 5, 6},
new [] {7, 8, 9}
};
How can I enumerate this collection so that I obtain IEnumerable<int> collections made up of the first items, second items, etc.?
That is, {1, 4, 7}, {2, 5, 8}, ...
(Though the implementation I've chosen is int[] objects, assume you only have IEnumerable<int> functionality. Thanks.)
Here's an approach that uses a generator instead of recursion. There's less array construction too, so it might be faster, but that's totally conjecture.
public static IEnumerable<IEnumerable<T>> Transpose<T>(
this IEnumerable<IEnumerable<T>> #this)
{
var enumerators = #this.Select(t => t.GetEnumerator())
.Where(e => e.MoveNext());
while (enumerators.Any()) {
yield return enumerators.Select(e => e.Current);
enumerators = enumerators.Where(e => e.MoveNext());
}
}
Just my 2 cents
In pure linq:
var transpond = collection.First().Select((frow,i)=>collection.Select(row=>row.ElementAt(i)));
Or with some inpurity:
var r1 = collection.First().Select((frow, i) => collection.Select(row => row.ToArray()[i]));
Code credit goes here (untested but looks fine).
public static class LinqExtensions
{
public static IEnumerable<IEnumerable<T>> Transpose<T>(this IEnumerable<IEnumerable<T>> values)
{
if (!values.Any())
return values;
if (!values.First().Any())
return Transpose(values.Skip(1));
var x = values.First().First();
var xs = values.First().Skip(1);
var xss = values.Skip(1);
return
new[] {new[] {x}
.Concat(xss.Select(ht => ht.First()))}
.Concat(new[] { xs }
.Concat(xss.Select(ht => ht.Skip(1)))
.Transpose());
}
}
//Input: transpose [[1,2,3],[4,5,6],[7,8,9]]
//Output: [[1,4,7],[2,5,8],[3,6,9]]
var result = new[] {new[] {1, 2, 3}, new[] {4, 5, 6}, new[] {7, 8, 9}}.Transpose();
Assuming all the sequences are of the same length.
static void Main(string[] args)
{
IEnumerable<IEnumerable<int>> collection =
new[]
{
new [] {1, 2, 3},
new [] {4, 5, 6 },
new [] {7, 8, 9}
};
Console.WriteLine("\tInitial");
Print(collection);
var transposed =
Enumerable.Range(0, collection.First().Count())
.Select(i => collection.Select(j => j.ElementAt(i)));
Console.WriteLine("\tTransposed");
Print(transposed);
}
static void Print<T>(IEnumerable<IEnumerable<T>> collection)=>
Console.WriteLine(string.Join(Environment.NewLine, collection.Select(i => string.Join(" ", i))));
Gives:
Initial
1 2 3
4 5 6
7 8 9
Transposed
1 4 7
2 5 8
3 6 9
If all elements are guaranteed to be the same length, you could do this:
IEnumerable<IEnumerable<int>> Transpose(IEnumerable<IEnumerable<int>> collection)
{
var width = collection.First().Count();
var flattened = collection.SelectMany(c => c).ToArray();
var height = flattened.Length / width;
var result = new int[width][];
for (int i = 0; i < width; i++)
{
result[i] = new int[height];
for (int j = i, k = 0; j < flattened.Length; j += width, k++)
result[i][k] = flattened[j];
}
return result;
}