How to calculate daily total? [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
i have this code and its working but i want it to return dailyTotals list with four values, at the moment it is being returned with three values ... i cant seem to figure out how to make it return dailyTotals with four values. BTW the billTotals and dateList are of the same lengh which is currently 7 and they will grow. billTotals and dateList will always remain the same length
List<double> dailyTotals = new List<double>();
string dateValue = "";
double oneDayTotal = 0;
int n = 0;
for (int i = 0; i < billTotals.Count; i += n)
{
dateValue = dateList[i];
oneDayTotal = 0;
while (dateValue == dateList[n])
{
oneDayTotal += billTotals[n];
n++;
}
dailyTotals.Add(oneDayTotal);
}
return dailyTotals;
[EDIT]: Im sorry i should have written this before :/
in the database i have billTotals and the date for each bill stored. so, one date can have multiple bills associated with it. what im trying to do is grab one months data and sum the totals for each day. so the logic i used in the while loop is supposed to sum up the totals while the date is the same ... i hope this makes the scenario more clear. :)

You never reset n, so you are increasing i by increasingly large amount, skipping over some numbers.
You need to set n = 0 inside the loop.
int n = 0;
for (int i = 0; i < billTotals.Count; i += n)
{
dateValue = dateList[i];
oneDayTotal = 0;
n = 0; // This counts the number of equal dates.
while (i + n < dateList.Length && dateValue == dateList[i + n])
{
oneDayTotal += billTotals[i + n];
n++;
}
dailyTotals.Add(oneDayTotal);
}
return dailyTotals;
You could also rewrite the code entirely to simplify it and avoid this curious way of incrementing your loop variable. I would suggest creating an array of objects that hold both the date and the total, then you can use LINQ to solve your problem without any complex loops:
var dailyTotals = datesAndTotals
.GroupBy(x => x.Date)
.Select(g => g.Sum(x => x.BillTotal))
.ToList();
You can also use Zip instead of creating a separate class, though it will be more readable with the class.

Related

Fill in numbers in order between two numbers [closed]

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 3 months ago.
Improve this question
Let's say you have two numbers, 4 and 9. The numbers can't be less than 0 or more than 9.
I want to fill the gap between 4 and 9 with numbers in correct order like so:
456789
How does one exactly do so? I've been stuck on this problem for the past 2 hours.
Thank you.
I have tried putting the numbers into an array and using the array's length as a way to fill in the numbers.
I've tried numerous other things that I don't know how to explain.
Just create a loop and loop thru all the integers between your numbers and add each number to a string if that is your desired output:
string CreateNumberSequence(int start, int end){
var sb = new StringBuilder();
for(int i = start; i <= end; i++){
sb.Add(i.ToString());
}
return sb.ToString();
}
Note that 10-12 would produce 101112, so you might want to add some separator between numbers, or just create a list of numbers and do the formatting separatly. You could also use Enumerable.Range, but if you are new to programming it is useful to know how to use plain loops.
If you want a list of numbers, change StringBuilder to List<int>, remove all the .ToString() and change the return-type. Or just use the previously mentioned Enumerable.Range.
You can use Enumerable.Range
int start = 4, end = 10;
int[] range = Enumerable.Range(start, end - start + 1).ToArray();
// range: 4 5 6 7 8 9 10
You can use the range method. since you know the start and end of the sequence you can put the start as 4 and the difference to the end from counting all the way from start will be 6.
and for 10-12 it will be like
var number = Enumerable.Range(10, 3);
var number = Enumerable.Range(4, 6);
var result = string.Join("", number.Select(x => x.ToString()).ToArray());
With extension methods :
public static class Ext
{
public static bool ToIntValue(this IEnumerable<int> source, out int output)
{
string joinedSource = string.Join(string.Empty, source);
return int.TryParse(joinedSource, out output);
}
public static IEnumerable<int> NumbersBetween(this int start, int end)
{
if (start > 0 && end <= 9 && start <= end)
{
for (int i = start; i <= end; i++)
yield return i;
}
else
{
throw new ArgumentException("Start and end must be beetween 1 and 9 and end must be bigger than start.");
}
}
}
use case :
if (1.NumbersBetween(9).ToIntValue(out int result))
{
Console.WriteLine(result);
}

Integer array Get difference between two highest numbers [closed]

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 4 years ago.
Improve this question
I have a List<int[]> that I populated by splitting an integer array into 4 groups. Now I need to get the difference of the two highest numbers in the array. I tried Array.Sort but I am stuck on how to continue.
What I have done so far?
public static void solution(int[] T)
{
List<int[]> splitted = new List<int[]>();//This list will contain all the splitted arrays.
int lengthToSplit = T.Length / 4;
int arrayLength = T.Length;
for (int i = 0; i < arrayLength; i = i + lengthToSplit)
{
int[] val = new int[lengthToSplit];
if (arrayLength < i + lengthToSplit)
{
lengthToSplit = arrayLength - i;
}
Array.Copy(T, i, val, 0, lengthToSplit);
splitted.Add(val);
}
//this is the part where I must get the difference between the two highest numbers in an integer array and put into another list.
foreach (int[] integerarray in splitted)
{
//get the difference of the two highest numbers per integer array and place it on another List<int>
}
}
get the difference between the two highest numbers in an integer array
and put into another list
You can use LINQ and Math.Abs:
List<int> differenceList = splitted
.Select(list => list.OrderByDescending(i => i).Take(2).ToArray())
.Select(highestTwo => Math.Abs(highestTwo[0] - highestTwo[1]))
.ToList();

Storing info from a database in an array [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Hi I need to work out the average of 10 integers stored in a database.
This is what I've got so far.
private void getAverage()
{
StudentsDataSet.StudentsRow courseMarks = studentsDataSet.Students.Course[10];
average = 0;
int[] array;
for (int index = 0; index < 10 ; index++)
{
average += array[index];
}
average = average / 10;
averageBox.Text = average.ToString();
}
As you can see I have no idea what I'm doing... any pointers??
There are a couple of issues with your code, which I will address one by one:
You are always getting the data from row 11 of your data table (studentsDataSet.Students.Course[10]). That's probably not what you want.
You are declaring your array but you are not initializing it.
You need to fill the array before you loop over it.
You are repeating the number of courses (10) in many places in your code (e.g. the for loop and the divisor of the average). This will be a source of errors when the number of courses changes.
Be careful to choose good names for your variables. average should be sum (that's what it actually stores) and array is a poor choice, because it does not describe the content of the variable, but its format.
According to the C# naming convention methods are in PascalCase.
Here is some code that will do the job. I have added comments to explain exactly what is happening:
//The method that will add the average to the text box. You need to provide the row index.
//One common way to get the row index would be the SelectedIndex of your data grid
private void GetAverage(int rowIndex)
{
//Get the row whose data you want to process
DataRow courseMarks = studentsDataSet.Students.Rows[rowIndex];
//Initialize an array with the names of the source columns
string[] courseColumnNames = { "Course1", "Course2", "Course3", "Course4", "Course5",
"Course6", "Course7", "Course8", "Course9", "Course10" };
//Declare and initialize the array for the marks
int[] markValues = new int[courseColumnNames.Length];
//Fill the array with data
for (int index = 0; index < courseMarks.Length ; index++)
{
//Get the column name of the current course
string columnName = courseColumnNames[index];
//Copy the column value into the array
markValues[index] = (int)courseMarks[columnName];
}
//Calculate the sum
int sum = 0;
for (int index = 0; index < courseMarks.Length ; index++)
{
sum += markValues[index];
}
//Calculate the average from the sum
//Note: Since it's an integer division there will be no decimals
int average = sum / courseMarks.Length;
//Display the data
averageBox.Text = average.ToString();
}
Note that of course you could merge the two loops into one (and even drop the array, since you could just directly add to the sum variable). I have not done that to keep every step of the process clearly separated. You could also use the LINQ method Average, but that would quite miss the point here.
Instead of all your codes, you may try this:
private double GetAverage()
{
StudentsDataSet.StudentsRow courseMarks = studentsDataSet.Students.Course[10];
var average=courseMarks.Average(x =>(double) x["*YourDataColumnName*"]);
return average;
}
Where YourDataColumnName is the column of your row which contains the value you want to get average of that
You could do the following :
int average = studentsDataSet.Students.Course.Average();
You would have to add using System.Linq; for this to work.

Is there a way to remove range of items in string array C# [closed]

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 5 years ago.
Improve this question
For example
private string[] oras = { "07:00AM", "07:30AM", "08:00AM", "08:30AM", "09:00AM", "10:00AM", " 10:30AM", "11:00AM", "11:30AM", "12:00PM", "12:30PM", "01:00PM", "01:30PM", "02:00PM", "02:30PM", "03:00PM", "03:30PM", "04:00PM", "04:30PM", "05:00PM", "05:30PM", "06:00PM", "06:30PM", "07:00PM", "07:30PM", "08:00PM" };
i want to remove items between "7:00AM" and "10:30AM"
Steps:
Convert to TimeSpan;
Filter where the time span doesn't meet your criteria;
Optionally convert back to string and/or an array.
Code:
var orasTs = oras.Select(o => ParseTimeSpan(o))
.Where(ts => !(ts.TotalHours >= 7 && ts.TotalHours <= 10.5f))
.ToArray();
private static TimeSpan ParseTimeSpan(string t)
{
int hoursToAdd = 0;
if (t.EndsWith("AM"))
{
hoursToAdd = 0;
}
else
{
hoursToAdd = 12;
}
return TimeSpan.Parse(t.Substring(0, 5)).Add(TimeSpan.FromHours(hoursToAdd));
}
You can try this. What I am doing here is that I am converting first the time and select based on your condition. Then return the result that should not match on the first result:
string[] oras = { "07:00AM", "07:30AM", "08:00AM", "08:30AM", "09:00AM", "10:00AM", " 10:30AM", "11:00AM", "11:30AM", "12:00PM", "12:30PM", "01:00PM", "01:30PM", "02:00PM", "02:30PM", "03:00PM", "03:30PM", "04:00PM", "04:30PM", "05:00PM", "05:30PM", "06:00PM", "06:30PM", "07:00PM", "07:30PM", "08:00PM" };
var res = oras.Where(c => DateTime.Parse(c) >= DateTime.Parse("07:00AM") && DateTime.Parse(c) <= DateTime.Parse("10:30AM"))
.ToArray();
var result = oras.Where(b => !res.Any(c => c == b)).ToArray();
Short answer, no. You cannot "Remove" or "Add" to arrays directly.
You can however use Array.Resize to resize the referenced array, or just straight up make a new one with a different element count.
This is not however answering the question you are ACTUALLY asking, for any given set of strings, how do you remove, conditionally, a portion of them.
I will assume going forwards you are/can use linq (System.Linq) and we will use oras.
Is it Time?
Given your example data, if you know they will all be "time" strings, you should parse to a strongly typed time object, probably TimeSpan like this
var myTimeSpans = oras.Select(o => TimeSpan.Parse(o));
using your new list of TimeSpan instances, you can then select only the elements that you do want using a Linq Where statement.
var myWantedTimespans = myTimeSpans.Where(ts => ts.TotalHours < 7 || ts.TotalHours > 10.5f);
This will get all TimeSpans where the total hours are lower than 7, or greater than 10.5. Modify as required for different conditional requirements.
you can then further utilise them in a strongly typed fashion in your new collection, or cast them back to string for whatever stringly typed purposes you may have.
Is it just strings?
If it's just arbitrary string values in an array, we can still get a theoretical Range removed, but it's a bit more messy. If you take the strings at face value, you can get a Range removed by using the base string comparer. For example:
string lower = "07:00AM";
string upper = "10:30AM";
var newArray = oras.Where(f => string.Compare(f, lower) < 0 || string.Compare(f, upper) > 0).ToArray();
this will remove a string Range between 2 other string values. however this is taking all strings at face value, where their content is based on their character values individually and compared in that fashion. if there is any data that could be considered if it was in a strongly typed fashion this will not be considered in a string-only comparison.
Hope this helps.
Looks like you are having fun here :)
Here's my realization:
string format = "hh:mmtt";
DateTime excludeStart = DateTime.ParseExact("07:00AM", format, CultureInfo.InvariantCulture),
excludeEnd = DateTime.ParseExact("10:30AM", format, CultureInfo.InvariantCulture);
var result = oras
.Select(str => DateTime.ParseExact(str.Trim(), format, CultureInfo.InvariantCulture))
.Where(ts => ts < excludeStart || ts > excludeEnd)
.Select(ts => ts.ToString("hh:mmtt"))
.ToArray();
You can run it here
Another possible variant:
Convert your list items to DateTime
Calculate count of items for given range
Calculate the range's start element index
Use RemoveRange() method, after making list from your array
Convert back to string array
string[] oras = { "07:00AM", "07:30AM", "08:00AM", "08:30AM", "09:00AM", "10:00AM", " 10:30AM", "11:00AM", "11:30AM", "12:00PM", "12:30PM", "01:00PM", "01:30PM", "02:00PM", "02:30PM", "03:00PM", "03:30PM", "04:00PM", "04:30PM", "05:00PM", "05:30PM", "06:00PM", "06:30PM", "07:00PM", "07:30PM", "08:00PM" };
int elementsCount = oras.Select(DateTime.Parse)
.Count(c => c >= DateTime.Parse("07:00AM")
&& c <= DateTime.Parse("10:30AM"));
int startIndex = Array.IndexOf(oras, "07:00AM");
List<string> orasList = oras.ToList();
orasList.RemoveRange(startIndex, elementsCount);
oras = orasList.ToArray();
If you can use List, you can use List.RemoveRange
(MSDN)
List<string> listHour = new List<string>();
foreach(var item in oras){
listHour.Add(item);
}
listHour.RemoveRange(1,4);
oras = listHour.ToArray();

Can't add double values to list dynamically, System.ArgumentOutOfRangeException [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I always getting this following error:
'System.ArgumentOutOfRangeException'
I am receiving double inputs dynamically from a PLC. I am not able to save the inputs inside a list. I dont know why. can anyone help?
string str = stringArray[1];
double value = double.Parse(str, CultureInfo.InvariantCulture);
List<double> list = new List<double>();
List<double> result = new List<double>();
while (true)
{
int i;
for (i = 1; i < 3 - 1; ++i)
{
list.Add(value);
result[i] = (list[i - 1] + list[i] + list[i + 1]) / 3; //The error is here
dataHub.ServerTemp(result);
}
}
for (i = 1; i < 3 - 1; ++i)
is essentially the same as i = 1 (start with 1, but don't go as far as 2)
So what your code is trying to do is:
Add a double (value) to list list
Update the second item in list result (first problem, result is initially empty) with the average of first, second and third item in list (second problem - list has one element).
result[i] does not yet exist. That is why you are getting the out of range error.

Categories