Adding the calculated sum of a list to another list - c#

I have a list of int .. How can i sum all the numbers in the list and get the result ?
List<int> FineListy = new List<int>();

Your code has a number of issues.
List<int> FineListy = new List<int>();
for (int i = 0; i < fineList.Count(); i++)
{
if (fineList[i] > 0)
{
FineListy.Add((fineList[i] += fineList[i]));
}
}
Firstly: C# naming conventions are such that local variables should start with lowercase letters and be camelCased. I recommend naming your variables totalsList and fineList respectively. For the sake of simplicity, I will use your current naming conventions below.
Next, you're doing FineListy.Add(fineList[i] += fineList[i]); which is the same as:
fineList[i] = fineList[i] * 2;
FineListy.Add(fineList[i]);
And you're doing it in a loop, so you will simply get a list of all items multiplied by 2.
Now you could fix this like so:
int total = 0;
for (int i = 0; i < fineList.Count; ++i)
{
if (fineList[i] > 0)
{
total += fineList[i];
}
}
FineListy.Add(total);
But you can use LINQ to do the same in a single line (I've split it across multiple lines to make it easier to read):
var total = fineList
.Where(v => v > 0)
.Sum();
FineListy.Add(total);
Or simply:
FineListy.Add(fineList.Where(v => v > 0).Sum());

If you have a list of int, why not use sum function??
int sum = FineListy.Sum();
This will add up all the numbers and give you the expected result.Now i see you do an If check to see if the number is not 0.So,create a new list then and pass the numbers to the list only if it's greater than 0
List<int> NewList = new List<int>;
foreach (var number in IntegerList)
{
if (number > 0)
{
NewList.Add(number);
}
}
Finally get the sum total :
int sum = NewList.Sum();
Or one-line LINQ solution :
var result = fineList.Where(a => a > 0).Sum();
NewList.Add(result );

Yes, it doubles, because that's what you do here :
FineListy.Add((fineList[i] += fineList[i]));
You say : "Add me fineList[i] + fineList[i] to my resulting collection FineListy"
So you got all elements doubled.
If you want to add values you don't need list just a variable to store it and LINQ .Sum() method
P.S.
I mean either one of these two (as others suggested):
FineListy.Add(fineList.Sum());
Or
int sum = fineList.Sum();

Related

How can i get the highest integer from a list string

I have a video clip which contains a bunch of Meta data (Mostly single line of strings), which in turn are linked to a specific frame. I managed to separate the speed data from each line of the Meta data and store it with in another list lc4_highest_speed_2
for (int h = 0; h < lc4_file_calculations.Count; h++)
{
string hold_variable = lc4_file_calculations[h].Replace("-", ",");
var mySplitResult2 = hold_variable.Split(',');
var speed = mySplitResult2[mySplitResult2.Length - 45];
lc4_highest_speed.Add(speed + ":" + h);
}
for (int f = 0; f < lc4_highest_speed.Count; f++)
{
string hoe3 = lc4_highest_speed[f];
var mySplitResult3 = hoe3.Split(':');
var speed2 = mySplitResult3[mySplitResult3.Length - 2];
var speed3 = mySplitResult3[mySplitResult3.Length - 1];
string speed_test = speed2.ToString();
lc4_highest_speed_2.Add(speed2 + " - " + speed3);
}
The new list holds data like this 012 - 82 the first part before the - is the speed and the other is the index number related to value from another string. I have tried things like concat, however it hasn’t worked. What would be the best way to get the highest speed the element before the - while also keeping the relation of the index number the number after the -.
Thank you
Try following :
string[] input = {
"012 - 82",
"012 - 83",
"012 - 84",
"012 - 85",
"012 - 86",
"012 - 87",
"13 - 102",
"13 - 103",
"13 - 104",
"13 - 105",
"13 - 106"
};
var output = input
.Select(x => x.Split(new char[] { '-' }))
.Select(x => new { speed = int.Parse(x.First()), index = int.Parse(x.Last()) })
.OrderByDescending(x => x.speed)
.GroupBy(x => x.speed)
.First()
.ToList();
A solution in O(n) time complexity return the higher speed value with its high index value.
int highestSpeed = 0;
int indexNumber = 0;
foreach (var item in lc4_highest_speed_2)
{
var values = item.Split('-');
if (values?.Count() == 2)
{
int.TryParse(values[0], out int parsedValue);
if (parsedValue > highestSpeed)
{
highestSpeed = parsedValue;
int.TryParse(values[1], out indexNumber);
continue;
}
int.TryParse(values[1], out int parsedIndex);
if (highestSpeed == parsedValue && parsedIndex > indexNumber) indexNumber = parsedIndex;
}
}
You can leverage a tuple to do this. Tuples automatically define an ordering based on their members that implement IComparable<T>. (Comparison is done in the order that the tuple's members are declared.)
Since an int implements IComparable<T> if we construct a tuple with the first element being the integer speed and the second the integer index, then the comparison operation generated for the tuple will be exactly what you need.
Thus you can solve this with a Linq expression that splits each row into the speed and index strings, parses those strings into ints and creates a tuple for each pair of speed and index. Then you can find the biggest using IEnumerable.Max():
var max = lc4_highest_speed_2.Select(item =>
{
var elements = item.Split("-");
return (speed: int.Parse(elements[0].Trim()), index: int.Parse(elements[1].Trim()));
}).Max();
Note that max is a tuple with an int first element called speed and an int second element called index.
Try it on .Net Fiddle
You can store all the speed value in the list of integer where you can find the mx value and using its index you then can find the relation between the speed and index value.
For the reference, I have created the small program. Hope you will understand
using System;
using System.Collections.Generic;
using System.Linq;
class HelloWorld {
static void Main() {
List<string> data = new List<string>();
List<int> intdata = new List<int>();
data.Add("012 - 82");
data.Add("013 - 102");
for(int i=0;i<data.Count;i++){
intdata.Add(Int16.Parse(data[i].Substring(0,data[i].IndexOf("-"))));
}
Console.WriteLine(intdata.Max());
}
}
Another way to do it:
var maxSpeed = lc4.Max(x => Convert.ToInt32(x.Split(' ')[0]));
var maxLine = lc4.FirstOrDefault(x => x.StartsWith($"{maxSpeed} "));
var maxIndex = Convert.ToInt32(maxLine.Split('-')[1].Substring(1));
or if you want all indices:
var maxSpeed = lc4.Max(x => Convert.ToInt32(x.Split(' ')[0]));
var maxLines = lc4.Where(x => x.StartsWith($"{maxSpeed} "));
var maxIndexes = maxLines.Select(x => Convert.ToInt32(x.Split('-')[1].Substring(1)));

Scheduler algorithm that fill remaning hours to work

I need to generate all possible values to a scheduler who works like this:
Some hours of the week can be already chosen.
The week of work is defined by the following pattern "???????" question marks can be replaced.
Given a maximum of hours, I need to replace the question marks with digits so that the sum of the scheduled hours match the hours need to work in a week returning a string array with all possible schedules, ordered lexicographically.
Example:
pattern = "08??840",
required_week_hours= 24
In this example, there are only 4 hours left to work.
calling this:
function List<String> GenerateScheduler(int workHours, int dayHours, string pattern){}
public static void Main(){
GenerateScheduler(24, 4, "08??840");
}
This would return the following list of strings:
0804840
0813840
.......
.......
0840840
I'm not very familiar with algorithms, which one I could use to solve this problem?
This sounds like a problem where you have to generate all permutations of a list of a certain amount of numbers that sum up to a certain number. First, you need to sum up the hours you already know. Then you need to count up the number of ? aka the number of shifts/days you do not know about. Using these parameters, this is what the solution will look like,
public List<string> GenerateScheduler(int workHours, int dayHours, string pattern){
int remainingSum = workHours;
int unknownCount = 0;
// first iterate through the pattern to know how many ? characters there are
// as well as the number of hours remaining
for (int i = 0; i < pattern.Length; i++) {
if (pattern[i] == '?') {
unknownCount++;
}
else {
remainingSum -= pattern[i] - '0';
}
}
List<List<int>> permutations = new List<List<int>>();
// get all the lists of work shifts that sum to the remaining number of hours
// the number of work shifts in each list is the number of ? characters in pattern
GeneratePermutations(permutations, workHours, unknownCount);
// after getting all the permutations, we need to iterate through the pattern
// for each permutation to construct a list of schedules to return
List<string> schedules = new List<string>();
foreach (List<int> permutation in permutation) {
StringBuilder newSchedule = new StringBuilder();
int permCount = 0;
for (int i = 0; i < pattern.Length(); i++) {
if (pattern[i] == '?') {
newSchedule.Append(permutation[permCount]);
permCount++;
}
else {
newSchedule.Append(pattern[i]);
}
}
schedules.Add(newSchedule.ToString());
}
return schedules;
}
public void GeneratePermutations(List<List<int>> permutations, int workHours, int unknownCount) {
for (int i = 0; i <= workHours; i++) {
List<int> permutation = new List<int>();
permutation.Add(i);
GeneratePermuationsHelper(permutations, permutation, workHours - i, unknownCount - 1);
}
}
public void GeneratePermutationsHelper(List<List<int>> permutations, List<int> permutation, int remainingHours, int remainingShifts){
if (remainingShifts == 0 && remainingHours == 0) {
permutations.Add(permutation);
return;
}
if (remainingHours <= 0 || remainingShifts <= 0) {
return;
}
for (int i = 0; i <= remainingHours; i++) {
List<int> newPermutation = new List<int>(permutation);
newPermutation.Add(i);
GeneratePermutationsHelper(permutations, newPermutation, remainingHours - i, remainingShifts - 1);
}
}
This can be a lot to digest so I will briefly go over how the permutation recursive helper function works. The parameters go as follows:
a list containing all the permutations
the current permutation being examined
the remaining number of hours needed to reach the total work hour count
the number of remaining shifts (basically number of '?' - permutation.Count)
First, we check to see if the current permutation meets the criteria that the total of its work hours equals the amount of hours remaining needed to complete the pattern and the number of shifts in the permutation equals the number of question marks in the pattern. If it does, then we add this permutation to the list of permutations. If it doesn't, we check to see if the total amount of work hours surpasses the amount of hours remaining or if the number of shifts has reached the number of question marks in the pattern. If so, then the permutation is not added. However, if we can still add more shifts, we will run a loop from i = 0 to remainingHours and make a copy of the permutation while adding i to this copied list in each iteration of the loop. Then, we will adjust the remaining hours and remaining shifts accordingly before calling the helper function recursively with the copied permutation.
Lastly, we can use these permutations to create a list of new schedules, replacing the ? characters in the pattern with the numbers from each permutation.
As per OP, you already know the remaining hours, which I assume is given by the parameter dayHours. So, if you were to break down the problem further, you would need to replace '?' characters with numbers so that, sum of new character(number) is equal to remaining hours(dayHours).
You can do the following.
public IEnumerable<string> GenerateScheduler(int totalHours,int remainingHours,string replacementString)
{
var numberOfPlaces = replacementString.Count(x => x == '?');
var minValue = remainingHours;
var maxValue = remainingHours * Math.Pow(10,numberOfPlaces-1);
var combinations = Enumerable.Range(remainingHours,(int)maxValue)
.Where(x=> SumOfDigit(x) == remainingHours).Select(x=>x.ToString().PadLeft(numberOfPlaces,'0').ToCharArray());
foreach(var item in combinations)
{
var i = 0;
yield return Regex.Replace(replacementString, "[?]", (m) => {return item[i++].ToString(); });
}
}
double SumOfDigit(int value)
{
int sum = 0;
while (value != 0)
{
int remainder;
value = Math.DivRem(value, 10, out remainder);
sum += remainder;
}
return sum;
}

copy items from a list on one condition

I am trying to copy items from a list to another list on one condition.
I have three lists. First list contains for example 10 lists of points, second list contains the total distance (cost or fitness) of each list (10 lists -> 10 total distances).
Here a picture:
first list contains 10 lists (each list contains points) - second list 'fitness'
Third list is empty and should be filled with items on one condition. First I added up all values in the second list.
Example with the numbers above: totalFitness = 4847 + 5153 + 5577 + 5324...
The condition to add list of points out of the first List to the third list is:
for example ----------> (Fitness[0] / totalFitness) <= ratio.
But it is not working, here you can see the code I tried:
class RunGA
{
public static List<List<Point3d>> createGenerations(List<List<Point3d>> firstGeneration, List<int> firstFitness, int generationSize)
{
List<List<Point3d>> currentGeneration = new List<List<Point3d>>();
int totalFitness;
int actualFitness;
totalFitness = firstFitness[0] + firstFitness[1];
double ratio = 1 / 10;
for(int k = 2; k < firstFitness.Count; k++)
{
actualFitness = firstFitness[k];
totalFitness += actualFitness;
}
for(int i = 0; i < firstFitness.Count; i++)
{
double selected = firstFitness[i] / totalFitness;
if(selected < ratio)
{
currentGeneration.Add(firstGeneration[i]);
}
}
return currentGeneration;
}
}
The third list is still empty. If I change the condition to: if(selected <= ratio)
then the whole list of points in the first list are being copied to the third list. However what I want to copy is: the list of points which has the 'best' fitness.
What is it that I'm doing wrong? I have absolutely no clue and I tried already a few changes, but it is still not working. I would appreciate it if you can consider that I'm a beginner.
I found another solution for this problem.
I still have these data:
List1:
ListOfPoints = a
ListOfPoints = b
ListOfPoints = c
ListOfPoints = d
List2:
Fitness of a
Fitness of b
Fitness of c
Fitness of d
What I wanted to achieve was: Take those ListOfPoints, which has the best Fitness and put them into a List3. All the rest ListOfPoints, put them into another List4.
This is the solution I thought of:
put List1 as Keys and List2 as Values into a Dictionary and sort it via LINQ. Now transfer the sorted Keys into a List3. With a for- Loop put the first half of the sorted List into List4 and the second half into List5.
Here is my Code:
List<List<Point3d>> currentGeneration = handoverPopulation.ToList();
List<double> currentFitness = handoverFitness.ToList();
Dictionary<List<Point3d>, double> dict = new Dictionary<List<Point3d>, double>();
foreach(List<Point3d> key in currentGeneration)
{
foreach(double valuee in currentFitness)
{
if(!dict.ContainsKey(key))
{
if(!dict.ContainsValue(valuee))
{dict.Add(key, valuee);}
}
}
}
var item = from pair in dict orderby pair.Value ascending select pair;
List<List<Point3d>> currentGenerationSorted = new List<List<Point3d>>();
currentGenerationSorted = item.Select(kvp => kvp.Key).ToList();
List<List<Point3d>> newGeneration = new List<List<Point3d>>();
List<List<Point3d>> newGenerationExtra = new List<List<Point3d>>();
int p = currentGenerationSorted.Count / 2;
for(int i = 0; i < p; i++)
{newGeneration.Add(currentGenerationSorted[i]);}
for(int j = p; j < currentGenerationSorted.Count; j++)
{newGenerationExtra.Add(currentGenerationSorted[j]);}
Hope this helps others who face the same problem.

Aggregate value takes very long time

I have one big list of 15 min values for oround year. and I would like to aggregate them into hours. I am doing it in very simple way :
for (; from <= to; from = from.AddHours(1))
{
List<DataPoint> valuesToAgregate = data.Where(x => x.TimeStamp >= from && x.TimeStamp < from.AddHours(1)).ToList();
dailyInputData.Add(valuesToAgregate.Sum(x=>x.Val));
}
This way it takes a lot of time, like 30 seconds for 35k of values, is there any way to optimize it ? maybe use ordering functionality or some how add index to list or using grouping by instead of for loop?
Of course, if you order your list by TimeStamp previously, this will work quicker. Example:
var orderedData = data.OrderBy(item => item.TimeStamp).ToList();
int firstIndex = 0;
var from = orderedData.First().TimeStamp;
var to = orderedData.Last().TimeStamp;
while (from < to)
{
var sum = 0;
var newTo = from.AddHours(1);
while (firstIndex < data.Count && orderedData[firstIndex].TimeStamp < newTo)
{
sum += orderedData[firstIndex].Val;
++firstIndex;
}
dailyInputData.Add(sum);
from = from.AddHours(1);
}
data = data.Sort(x=>x.TimeStamp);
int counter = 0;
var boundary = from.AddHours(1);
foreach(var d in data){
if(d.TimeStamp > boundary){
boundary = boundary.AddHours(1);
counter = 0;
dailyInputData.Add(counter);
}
++counter;
}
This problem lies in the logic
the list is scanned from start to end every time to find the candidate values (your where clause)
the candidate values are inserted to another temp list
the temp list is THEN scanned from start to end to calculate the sum
The fastest approach:
sort the list
go through the items, if they belong to the current group, add the counter, otherwise you've jumped to a new group, flush the counter to record the value and start it over again

Why does this simple code not work (ArgumentOutOfRangeException)

int i = 0;
int x = 10;
List<int> group = new List<int>();
while (i < x)
{
RichTextBoxShowTafel.AppendText(Convert.ToString(group[i]));
i++;
}
Why does this not work? I want to display the first 10 numbers of the List called: "group".
edit:
I actually want to create variables and print it in a row...
You never put anything in the group variable. You only instantiated an empty list.
And you'd be better off doing this:
foreach (int item in group)
{
RichTextBoxShowTafel.AppendText(item.ToString());
}
Because group is empty? As it has no elements, you can't access group[0], which is what you do in the first iteration
This is because group is empty!
When your loop first executes then i = 0 then you try Convert.ToString(groups[i]) which will always fail as there is no index of 0 in group
You should add elements in the list before you try to get them. The is the reason you got ArgumentOutOfRangeException. You can avoid the exception by adding element first.
int i = 0;
int x = 10;
List<int> group = new List<int>();
while (i < x)
{
group.Add(i);
RichTextBoxShowTafel.AppendText(Convert.ToString(group[i]));
i++;
}
If you are expecting group to be populated with numbers, you will have to do that yourself. Declaring and initializing it List<int> group = new List<int>(); only creates it. There is nothing inside. If you want to try putting variables in you can do something like this:
for(int j = 0; j < 10; j++)
{
group.Add(j);
}

Categories

Resources