return accumulated values with Aggregate? - c#

I have a list of Int and would like to 'fold' it like: (((((0+1) + 2) + 3) + 4) +5)
and end up with with a list like the result variable.
var numbers = new List<int>() {1, 2, 3, 4, 5};
var sum = numbers.Aggregate((a, b) => a + b); // 15
var desiredResult = [1, 3, 6, 10, 15];
How can I update the Aggregate method to return the desired result?

The overloads to Aggregate all produce a single output an int. That's not what you're looking for. You want to project one array to another with a running sum. Something like this would work:
var runningSum = 0;
var sum = numbers.Select(i => runningSum += i);
sum =
[1 3 6 10 15]

Related

LINQ OrderBy then SELECT specific index

I have database table with a lot of data in it. I want to order it by column name TIMESTAMP, then select any given index of that generated List.
int index = 1;
query = dbContext.SimpleAisRecords
.OrderBy(ship => ship.TIMESTAMP)
// How to get wanted index: --> select/take(index)?;
The reason I wanna do this is because my table only has dummy-data, and I want to iterate through it. Therefore I want to call this method with desired index. First iteration index : 1, and next iteration index : 2 and so on.
I have seen a lot of questions on how to Select then OrderBy, OrderBy then Select and OrderBy then Take.
But as I said, I need a way to take a specific index of OrderBy, not the first or last item of that OrderBy.
Is that possible?
You can use overload of Where(the second parameter is index):
var model = new int[] { 1, 2, 3, 4, 5, 10, 9, 8, 7 };
var result = model.OrderBy(s => s).Where((s, i) => i > 5).ToList();
UPDATE:
We can include desired range of indexes and check them in Where:
var indexes = new List<int>{ 1, 8, 5 };
var model = new int[] { 1, 2, 3, 4, 5, 10, 9, 8, 7, 6 };
var result = model.OrderBy(s => s)
.Where((s, i) => indexes.Contains(i)).ToList();
You can select a specific item using ElementAt. E.g:
int index = 1;
query = dbContext.SimpleAisRecords
.OrderBy(ship => ship.TIMESTAMP)
.ElementAt(index)
More info: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.elementat
I understand that u want to return only wanted index?
if so, you have a lot of ways to do that.
use this if you want to iterate on the List
int index = 1;
query = dbContext.SimpleAisRecords
.OrderBy(ship => ship.TIMESTAMP).ToList();
var res = query [index ];
or you could do like this if u want to only return that value
int index = 1;
query = dbContext.SimpleAisRecords
.OrderBy(ship => ship.TIMESTAMP).Skip(index).Take(1).FirstOrDefault();
You can use this below code
int[] model = new int[] { 1, 2, 3, 4, 5, 10, 9, 8, 7 };
var result = model.OrderByDescending(x => x).Select((iVal, i) => new {i, iVal}).Where(x => (x.i == 3)).Select(x => x.iVal).FirstOrDefault();
Console.WriteLine((int)result);

Create an array of Tuple depending on an array of data in C#

Suppose I have this data int[] a = [1,2,3,4,5]
I would like to create Tuple<int,int,bool>[] where the first element is itself, the second is it's double value and the last element is whether it is an even number or not.
That is, the resulting data would be :
(1, 2, false)
(2, 4, true)
(3, 6, false)
(4, 8, true)
(5, 10, false)
One solution I have is to create a list, make a for loop over a array and new each Tuple, add to the list, and then finally use .ToArray on the list. But I think there must be an elegant way to do this. I don't mind using LINQ.
int[] a = [1, 2, 3, 4, 5];
List<Tuple<int,int,bool>> list = new List<Tuple<int, int, bool>>();
{
foreach(int i in a)
{
list.Add(new Tuple<int, int, bool>(i, i * 2, i % 2 == 0));
}
}
return list.ToArray();
A simple Select should do the trick:
var tuples = a.Select(v => Tuple.Create(v, v * 2, v % 2 == 0)).ToArray();
Using a select query would solve the problem.
int[] a = [1, 2, 3, 4, 5];
var result = a.Select(x => Tuple.Create<int, int, bool>(x, 2 * x, x % 2 == 0)).ToArray();

How to iterate through all subcollections of size K, in ascending order of their sums.

Suppose I have a sorted array such as
int[] sarr = new int[] { 0, 1, 3, 5 };
and I want to iterate through all combinations of size K in ascending order of their sum. For example, if K=2 then the combinations in order are
{0, 1} (sum = 1)
{1, 0} (sum = 1)
{0, 3} (sum = 3)
{3, 0} (sum = 3)
{3, 1} (sum = 4)
{1, 3} (sum = 4)
{5, 0} (sum = 5)
.
.
.
I want to do this without first getting all combinations because I want to stop as soon as I've found one that satisfies a condition Func<int[],bool> cond.
Is there a known way of doing this?
I would use yield return to describe all combinations, arrangements or whatever subcollections you want to generate and then use FirstOrDefault on the result.
That way you will only generate all subcollections if there isn't one you are looking for or the one you are looking for is the very last.
On about getting them ascending by the sum of the elements, sort the initial collection and then pick k elements from start to end. You can even generate combinations and from these to generate all possible permutations and thus you will get all your arrangements.
A quick way to get all combinations:
class Program
{
static void Main(string[] args)
{
var initialArray = new[] { 0, 1, 3, 5 };
var subArrayLength = 2;
foreach (var subArray in GetSubArrays(initialArray, subArrayLength))
Console.WriteLine($"[{string.Join(", ", subArray)}]");
Console.WriteLine("Searching for array that contains both 1 and 5.");
var arrayFulfillingCriteria = GetSubArrays(initialArray, subArrayLength).FirstOrDefault(array => array.Contains(1) && array.Contains(5));
if (arrayFulfillingCriteria != null)
Console.WriteLine($"[{string.Join(", ", arrayFulfillingCriteria)}]");
else
Console.WriteLine("No array found.");
}
static IEnumerable<int[]> GetSubArrays(int[] initialArray, int subArrayLength)
{
var indexStack = new Stack<int>(Enumerable.Range(0, subArrayLength));
do
{
var subArray = indexStack.Select(i => initialArray[i]).Reverse().ToArray();
yield return subArray;
var index = indexStack.Pop();
while (indexStack.Count != 0 && indexStack.Count < subArrayLength && index == initialArray.Length - (subArrayLength - indexStack.Count))
index = indexStack.Pop();
while (indexStack.Count < subArrayLength && index < initialArray.Length - (subArrayLength - indexStack.Count))
{
index++;
indexStack.Push(index);
}
}
while (indexStack.Count != 0);
}
}
The only reason I can think of where you would need arrangements (seeing as you order by sum) is that the items within the sub array need to be in a particular order.
Does this work for you?
Func<IEnumerable<int>, IEnumerable<IEnumerable<int>>> getAllSubsets = null;
getAllSubsets = xs =>
(xs == null || !xs.Any())
? Enumerable.Empty<IEnumerable<int>>()
: xs.Skip(1).Any()
? getAllSubsets(xs.Skip(1))
.SelectMany(ys => new [] { ys, xs.Take(1).Concat(ys) })
: new [] { Enumerable.Empty<int>(), xs.Take(1) };
Now, given this:
Func<int[],bool> cond = xs => true;
int[] sarr = new int[] { 0, 1, 3, 5, };
var result =
getAllSubsets(sarr)
.Where(xs => xs.Count() == 2)
.Where(xs => cond(xs.ToArray()));
I get this as the result:
{0, 1}
{0, 3}
{1, 3}
{0, 5}
{1, 5}
{3, 5}

comparing two lists and removing missing numbers with C#

there are two lists:
List<int> list2 = new List<int>(new[] { 1, 2, 3, 5, 6 }); // missing: 0 and 4
List<int> list1 = new List<int>(new[] { 0, 1, 2, 3, 4, 5, 6 });
how do you compare two lists, find missing numbers in List1 and remove these numbers from List1? To be more precise, I need to find a way to specify starting and ending position for comparison.
I imagine that the proccess should be very similar to this:
Step 1.
int start_num = 3; // we know that comparisons starts at number 3
int start = list2.IndexOf(start_num); // we get index of Number (3)
int end = start + 2; // get ending position
int end_num = list2[end]; // get ending number (6)
now we've got positions of numbers (and numbers themselves) for comparison in List2 (3,5,6)
Step 2. To get positions of numbers in List1 for comparison - we can do the following:
int startlist1 = list1.IndexOf(start_num); // starting position
int endlist1 = list1.IndexOf(end_num); // ending position
the range is following: (3,4,5,6)
Step 3. Comparison. Tricky part starts here and I need a help with it
Basically now we need to compare list2 at (3,5,6) with list1 at (3,4,5,6). The missing number is "4".
// I have troubles with this step but the result will be:
int remove_it = 4; // or int []
Step 4. Odd number removal.
int remove_it = 4;
list1 = list1.Where(a => a != remove_it).ToList();
works great, but what will happen if we have 2 missing numbers? i.e.
int remove_it = 4 // becomes int[] remove_it = {4, 0}
Result As you have guessed the result is new List1, without number 4 in it.
richTextBox1.Text = "" + string.Join(",", list1.ToArray()); // output: 0,1,2,3,5,6
textBox1.Text = "" + start + " " + start_num; // output: 2 3
textBox3.Text = "" + end + " " + end_num; // output: 4 6
textBox2.Text = "" + startlist1; // output: 3
textBox4.Text = "" + endlist1; // output: 6
Can you guy help me out with Step 3 or point me out to the right direction?
Also, can you say what will happen if starting number(start_num) is the last number, but I need to get next two numbers? In example from above numbers were 3,5,6, but they should be no different than 5,6,0 or 6,0,1 or 0,1,2.
Just answering the first part:
var list3 = list1.Intersect(list2);
This will set list3 to { 0, 1, 2, 3, 4, 5, 6 } - { 0, 4 } = { 1, 2, 3, 5, 6 }
And a reaction to step 1:
int start_num = 3; // we know that comparisons starts at number 3
int start = list2.IndexOf(start_num); // we get index of Number (3)
int end = start + 2; // get ending position
From where do you get all those magic numbers (3, + 2 ) ?
I think you are over-thinking this, a lot.
var result = list1.Intersect(list2)
You can add a .ToList on the end if you really need the result to be a list.
List<int> list2 = new List<int>(new[] { 1, 2, 3, 5, 6 }); // missing: 0 and 4
List<int> list1 = new List<int>(new[] { 0, 1, 2, 3, 4, 5, 6 });
// find items in list 2 notin 1
var exceptions = list1.Except(list2);
// or are you really wanting to do a union? (unique numbers in both arrays)
var uniquenumberlist = list1.Union(list2);
// or are you wanting to find common numbers in both arrays
var commonnumberslist = list1.Intersect(list2);
maybe you should work with OrderedList instead of List...
Something like this:
list1.RemoveAll(l=> !list2.Contains(l));
To get the numbers that exist in list1 but not in list2, you use the Except extension method:
IEnumerable<int> missing = list1.Except(list2);
To loop through this result to remove them from list1, you have to realise the result, otherwise it will read from the list while you are changing it, and you get an exception:
List<int> missing = list1.Except(list2).ToList();
Now you can just remove them:
foreach (int number in missing) {
list1.Remove(number);
}
I'm not sure I understand your issue, and I hope the solution I give you to be good for you.
You have 2 lists:
List list2 = new List(new[] { 1, 2, 3, 5, 6 }); // missing: 0 and 4
List list1 = new List(new[] { 0, 1, 2, 3, 4, 5, 6 });
To remove from list1 all the missing numbers in list2 I suggest this solution:
Build a new list with missing numbers:
List diff = new List();
then put all the numbers you need to remove in this list. Now the remove process should be simple, just take all the elements you added in diff and remove from list2.
Did I understand correctly that algorithm is:
1) take first number in List 2 and find such number in List1,
2) then remove everything from list 1 until you find second number form list2 (5)
3) repeat step 2) for next number in list2.?
You can use Intersect in conjunction with Skip and Take to get the intersection logic combined with a range (here we ignore the fact 0 is missing as we skip it):
static void Main(string[] args)
{
var list1 = new List<int> { 1, 2, 3, 4, 5 };
var list2 = new List<int> { 0, 1, 2, 3, 5, 6 };
foreach (var i in list2.Skip(3).Take(3).Intersect(list1))
Console.WriteLine(i); // Outputs 3 then 5.
Console.Read();
}
Though if I'm being really honest, I'm not sure what is being asked - the only thing I'm certain on is the intersect part:
var list1 = new List<int> { 1, 2, 3, 4, 5 };
var list2 = new List<int> { 0, 1, 2, 3, 5, 6 };
foreach (var i in list2.Intersect(list1))
Console.WriteLine(i); // Outputs 1, 2, 3, 5.
ok, seems like I hadn't explained the problem well enough, sorry about it. Anyone interested can understand what I meant by looking at this code:
List<int> list2 = new List<int>() { 1, 2, 3, 5, 6 }; // missing: 0 and 4
List<int> list1 = new List<int>() { 0, 1, 2, 3, 4, 5, 6 };
int number = 3; // starting position
int indexer = list2.BinarySearch(number);
if (indexer < 0)
{
list2.Insert(~index, number); // don't look at this part
}
// get indexes of "starting position"
int index1 = list1.Select((item, i) => new { Item = item, Index = i }).First(x => x.Item == number).Index;
int index2 = list2.Select((item, i) => new { Item = item, Index = i }).First(x => x.Item == number).Index;
// reorder lists starting at "starting position"
List<int> reorderedList1 = list1.Skip(index1).Concat(list1.Take(index1)).ToList(); //main big
List<int> reorderedList2 = list2.Skip(index2).Concat(list2.Take(index2)).ToList(); // main small
int end = 2; // get ending position: 2 numbers to the right
int end_num = reorderedList2[end]; // get ending number
int endlist1 = reorderedList1.IndexOf(end_num); // ending position
//get lists for comparison
reorderedList2 = reorderedList2.Take(end + 1).ToList();
reorderedList1 = reorderedList1.Take(endlist1 + 1).ToList();
//compare lists
var list3 = reorderedList1.Except(reorderedList2).ToList();
if (list3.Count != 0)
{
foreach (int item in list3)
{
list1 = list1.Where(x => x != item).ToList(); // remove from list
}
}
// list1 is the result that I wanted to see
if there are any ways to optimize this code please inform me. cheers.

Possible to group by Count in LINQ?

This might be either impossible or so obvious I keep passing over it.
I have a list of objects(let's say ints for this example):
List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6 };
I'd like to be able to group by pairs with no regard to order or any other comparison, returning a new IGrouping object.
ie,
list.GroupBy(i => someLogicToProductPairs);
There's the very real possibility I may be approaching this problem from the wrong angle, however, the goal is to group a set of objects by a constant capacity. Any help is greatly appreciated.
Do you mean like this:
List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6 };
IEnumerable<IGrouping<int,int>> groups =
list
.Select((n, i) => new { Group = i / 2, Value = n })
.GroupBy(g => g.Group, g => g.Value);
foreach (IGrouping<int, int> group in groups) {
Console.WriteLine(String.Join(", ", group.Select(n=>n.ToString()).ToArray()));
}
Output
1, 2
3, 4
5, 6
you can do something like this...
List<int> integers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var p = integers.Select((x, index) => new { Num = index / 2, Val = x })
.GroupBy(y => y.Num);
int counter = 0;
// this function returns the keys for our groups.
Func<int> keyGenerator =
() =>
{
int keyValue = counter / 2;
counter += 1;
return keyValue;
};
var groups = list.GroupBy(i => {return keyGenerator()});

Categories