Linq group by columns in a nested collection - c#

IEnumerable<IEnumerable<object>> rows = new List<List<object>
{
//Columns
new List<object> { 10, 20, 30, 40, 50 },
new List<object> { 10, 20, 30, 40, 50 },
new List<object> { 10, 20, 30, 40, 50 },
new List<object> { 10, 20, 30, 40, 50 }
}
I basically want to group all the 10's, 20's, 30's, 40's, 50's.
I want to do it using Linq and in the best possible way. Please take into consideration that the size of my collection can go upto 20 million or more.
I was able to achieve it by doing the following however it gives me out of memory exception when I do a for each on the group collection.
IEnumerable<IEnumerable<object>> rows = Enumerable.Repeat(new List<object> { 10, 20, 30, 40, 50 }, 20000000);
var group = rows.SelectMany(x => x.Select((InnerValue, Index) => new { Index, InnerValue })).GroupBy(x => x.Index);
EXPECTED RESULT BELOW:
var expectedResult = new List<List<object>
{
new List<object> { 10, 10, 10, 10, 10 },
new List<object> { 20, 20, 20, 20, 20 },
new List<object> { 30, 30, 30, 30, 30 },
new List<object> { 40, 40, 40, 40, 40 }
}
Thanks.

If you want to use linq :), you can do it with the following query:
List<List<object>> expectedResult =
rows.SelectMany(r => r)
.ToLookup(k => k, v => v)
.Select(kv => kv.ToList())
.ToList();

Related

How to get the even item positions in a list with LINQ

I have a list like this
List<double> points1 = new List<double>
{
10, 20, 30, 40, 50, 60, 70, 80, 90, 100
};
How can I get the even positions with LINQ in order to get a list like this
20,40,60,80,100
I know how to do it with a for loop, but I want this in a single line with LINQ
points1.Where((value, idx) => idx % 2 != 0);

Arrange Array in C# Issue

I've an array sequence 20,40,60,10,30,50. I want to sort this sequence into the following order 60,40,50,20,30,10 in C#.
Any Help? Thanks in advance☺
Very Simple if you have an Array
int[] arr = { 1, 2, 3, 5, 9, 0, 2, 10 };
arr.OrderBy(a => a);
arr.Reverse();
in case of list
List<int> abc = new List<int> { 1, 2, 3, 5, 9, 0, 2, 10 };
abc.Sort();
abc.Reverse();
Just use OrderByDescending of LINQ:
var list = new[] {20, 40, 60, 10, 30, 50};
var newList = list.OrderByDescending(x => x);
Console.WriteLine(string.Join(",", newList)); //60,50,40,30,20,10
You can try this
int[] array = new int[] { 20, 40, 60, 10, 30, 50 };
Array.Sort<int>(array,
new Comparison<int>((element1, element2) => element1.CompareTo(element2)));
to reverse sort
element2.CompareTo(element1)

How to multiply an element of List<double[]> by a scalar

Having a List<double[]> with data
List<double[]> sqlResult = new List<double[]>();
sqlResult.Add(new double[] { 11, 21, 31 });
sqlResult.Add(new double[] { 12, 22, 32 });
sqlResult.Add(new double[] { 13, 23, 33 });
sqlResult.Add(new double[] { 14, 24, 34 });
How can I multiply the third element of each row by -1 so I would get
{ 11, 21, -31 }
{ 12, 22, -32 }
{ 13, 23, -33 }
{ 14, 24, -34 }
Do not know how to do it with LINQ
sqlResult= sqlResult.Select(item => -item[2]).ToList();
If you avoid access by index, you won't get a exception if there are less than 3 elements within your List.
sqlResult = sqlResult.Select(x => x.Select((y, i) => i == 2 ? -y : y).ToArray()).ToList();
var result = sqlResult.Select(x => new double[] { x[0], x[1], x[2] * -1}).ToList();
Try this
sqlResult.ForEach(y => y[2]= y[2] * -1);

Speed up LINQ Object Query

I am attempting to speed up the following LINQ Object query:
var setOfCodes = codeList1
.SelectMany(q => q.Codes)
.Union(codeList2.SelectMany(q => q.Codes)
.Union(codeList3.SelectMany(q => q.Codes)
.ToList();
Where
codeListX is a List<Item>
and
public Item {
public List<int> Codes = new List<int>();
}
Example:
var codeList1 = new List<Item> {
new Item {
Codes = new List<int> {
100,
105,
110
}
},
new Item {
Codes = new List<int> {
100,
110,
115
}
},
};
var codeList2 = new List<Item> {
new Item {
Codes = new List<int> {
150,
155,
160
}
},
new Item {
Codes = new List<int> {
150,
155,
170
}
},
};
And the output should be (Not fussed about order, I can sort later):
100, 105, 110, 115, 150, 155, 160, 170
IE: Outputs a list containing all the codes that appear within the codeListX's.
Is there a faster way to do this?
You can write it like this :
var setOfCodes = new[] { codeList1, codeList2, codeList3 }
.SelectMany(x => x)
.SelectMany(x => x.Codes)
.Distinct()
.ToList();

How to group the same values in a sequence with LINQ?

I have a sequence. For example:
new [] { 10, 1, 1, 5, 25, 45, 45, 45, 40, 100, 1, 1, 2, 2, 3 }
Now I have to remove duplicated values without changing the overall order. For the sequence above:
new [] { 10, 1, 5, 25, 45, 40, 100, 1, 2, 3 }
How to do this with LINQ?
var list = new List<int> { 10, 1, 1, 5, 25, 45, 45, 45, 40, 100, 1, 1, 2, 2, 3 };
List<int> result = list.Where((x, index) =>
{
return index == 0 || x != list.ElementAt(index - 1) ? true : false;
}).ToList();
This returns what you want. Hope it helped.
var list = new List<int> { 10, 1, 1, 5, 25, 45, 45, 45, 40, 100, 1, 1, 2, 2, 3 };
var result = list.Where((item, index) => index == 0 || list[index - 1] != item);
It may be technically possible (though I don't think you can with a one-liner) to solve this with LINQ, but I think it's more elegant to write it yourself.
public static class ExtensionMethods
{
public static IEnumerable<T> PackGroups<T>(this IEnumerable<T> e)
{
T lastItem = default(T);
bool first = true;
foreach(T item in e)
{
if (!first && EqualityComparer<T>.Default.Equals(item, lastItem))
continue;
first = false;
yield return item;
lastItem = item;
}
}
}
You can use it like this:
int[] packed = myArray.PackGroups().ToArray();
It's unclear from the question what should be returned in the case of 1,1,2,3,3,1. Most answers given return 1,2,3, whereas mine returns 1,2,3,1.
You can use Contains and preserve order
List<int> newList = new List<int>();
foreach (int n in numbers)
if (newList.Count == 0 || newList.Last() != n)
newList.Add(n);
var newArray = newList.ToArray();
OUTPUT:
10, 1, 5, 25, 45, 40, 100, 1, 2, 3
Did you try Distinct?
var list = new [] { 10, 20, 20, 5, 25, 45, 45, 45, 40, 100, 1, 1, 2, 2, 3 };
list = list.Distinct();
Edit: Since you apparently only want to group items with the same values when consecutive, you could use the following:
var list = new[] { 10, 1, 1, 5, 25, 45, 45, 45, 40, 100, 1, 1, 2, 2, 3 };
List<int> result = new List<int>();
foreach (int item in list)
if (result.Any() == false || result.Last() != item)
result.Add(item);

Categories

Resources