Better way to update values in string[] - c#

I am looking for a better way to update values in my List/Array:
My code is like -
String[] values = baseValue.Split(new []{'+'});
Because the 'values' can have decimal/string values - I want to update items in this list to remove any value after decimal -
for (int i = 0; i < values.Count(); i++)
{
decimal newvalue;
if (Decimal.TryParse(values[i], out newvalue))
{
values[i] = Decimal.ToInt32(newvalue).ToString();
}
}
Is there a better way to achieve above using Linq/without Linq ?

You could use string operations, instead of converting to decimal then to int and finally back to string.
string[] values = baseValue.Split('+');
for (int i = 0; i < values.Length; i++)
{
int pos = values[i].IndexOf('.');
if (pos >= 0) {
values[i] = values[i].Substring(0, pos);
}
}
Of cause no rounding occurs here.
String.Split has an overload with one argument params char[] separator. Because of the params keyword, you can specify as many characters as you want, without having to create an array explicitly.
string[] result = s.Split('x', 'y', 'z');
Use values.Length which is a property built into array types. values.Count() is a LINQ extension method, which enumerates all the array items and is therefore not efficient.

You could use an extension method:
public static void ConvertDecimalToInts(this string[] values)
{
for (int i = 0; i < values.Count(); i++)
{
decimal newvalue;
if (Decimal.TryParse(values[i], out newvalue))
{
values[i] = Decimal.ToInt32(newvalue).ToString();
}
}
}
And use it as so:
String[] values = baseValue.Split(new[] { '+' });
values.ConvertDecimalToInts();

Olivier's answer is probably better in that it doesn't require three conversions, but you can do this with Linq if you wish:
values = baseValue.Split('+')
.Select(v => Decimal.ToInt32(Decimal.Parse(v)).ToString());

Related

How to fix the output after I compare two arrays in C#?

So I have this homework assignment that requires me to assign output to labels after I compare two arrays. My problem is that after I compare the two arrays, the output I assign is wrong. I'm supposed to out 'Y' if at a specific index of the two arrays are equal and 'N' if they're not equal but every time I run the code, it outputs 'Y' to all the labels no matter what. How can I fix what is being outputted after the comparison?
private void evaluateStudentAnswers()
{
/* Use a "for" loop to cycle through the answerKey[] and studentAnswers[] arrays, and compare the answers
* in the two arrays at each index. If they match, then increment the global variable "correctAnswers"
* and assign the value 'Y' to the corresponding index in the correctOrIncorrect[] array. if they
* don't match, then increment the global variable "incorrectAnswers" and assign the value 'N' to the
* corresponding indes in the correctOrIncorrec[] array. These two variables will be used to calculate
* the grade percentage.
*/
for (int i = 0; i < studentAnswers.Length; i++)
{
for(int j = 0; j < answerKey.Length; j++)
{
// I think the indexes below are being checked if they're the same and I need to make sure not just the
//indexes are the same but the values as well
if (studentAnswers[i] == answerKey[j])
{
correctAnswers++;
for(int k = 0; k < correctOrIncorrect.Length; k++)
{
correctOrIncorrect[k] = 'Y';
}
}
else
{
incorrectAnswers++;
for (int k = 0; k < correctOrIncorrect.Length; k++)
{
correctOrIncorrect[k] = 'N';
}
}
}
}
}
I think your code can be simplified quite a lot. assuming there's a 1-1 mapping between studentAnswers and answerKey.
for (int i = 0; i < studentAnswers.Length; i++)
{
var studentAnswer = studentAnswers[i];
var answer = answerKey[i];
if (studentAnswer == answer)
{
++correctAnswers;
correctOrIncorrect[i] = 'Y';
}
else
{
++incorrectAnswers;
correctOrIncorrect[i] = 'N'
}
}
All of the arrays are the same size. So when we loop over each answer the student provided, we know we can find the corresponding correct answer in answerKey. Also, the tracking of correct answers also follows the same pattern, for each studentAnswer, we want to record the correctness in correctOrIncorrect, which corresponds to the particular answer the student provided. As such, we only need to perform a single loop, since the i refers to the appropriate index in all the arrays as we're processing.
If studentAnswers.Length == answerKey.Length == correctOrIncorrect.Length
Then
for (int i = 0; i < studentAnswers.Length; i++)
{
if(studentAnswers[i] == answerKey[j])
{
correctAnswers++;
correctOrIncorrect[k] = 'Y';
}
else
{
incorrectAnswers++;
correctOrIncorrect[k] = 'N';
}
}
Since it is an assignment I wont give an answer :) but since you are stuck I encourage you use the guidance below.
These two are unnecessary in your code
inner for-loop on correctOrIncorrect[]
variable "k", you can use "i" instead for correctOrIncorrect value assignment
Since the arrays have to have the same size/order, you only need to loop through them once. Also I find ternary assignments more clear than if blocks:
Func<bool, int> toInt = (b) => b ? 1 : 0;
for (int i = 0; i < studentAnswers.Length; i++)
{
var studentAnswer = studentAnswers[i];
var answer = answerKey[i];
var isCorrect = studentAnswer == answer;
correctOrIncorrect[i] = isCorrect ? 'Y' : 'N';
correctAnswers = isCorrect ? 1 : 0; // toInt(isCorrect)
incorrectAnswers = !isCorrect ? 1 : 0; // toInt(!isCorrect)
}
}
Or in LINQ (just because it's worth learning, but probably not appropriate for homework):
correctOrIncorrect = answerKey.Zip(studentAnswer, (a,b) => a == b ? "Y" : "N").ToArray();
incorrectAnswers = correctOrIncorrect.Count(x => x == "Y");
...

Input string not in correct format exception c#

I have read data from a text file. I want to change data in that file into an Int array. I don't know why it wrong.
class Program
{
public static int[,] provincial = new int[100, 100];
public static void loadProvincial()
{
string[] s = System.IO.File.ReadAllLines("C:\\Users\\Lyn203\\Desktop\\data\\final-graph.txt");
for (int i = 0; i < s.Length; ++i)
{
string[] splitedArray = s[i].Replace("\t","_").Split('_');
//Console.WriteLine(splitedArray[i]);
for (int j = 0; j < splitedArray.Length-1; ++j)
{
provincial[i,j] = int.Parse(splitedArray[j].ToString());
}
}
Console.ReadLine();
}
static void Main(string[] args)
{
loadProvincial();
}
}
and TextFile:
http://textuploader.com/djhbe
I suggest you to call the overload of Split that removes the empty entries. In other words, if you have two consecutive tabs without a value between the two tabs your result will contain an empty string. That string is not convertible by Int32.Parse
string[] splitedArray = s[i].Replace("\t","_")
.Split(new char[] {'_'},
StringSplitOptions.RemoveEmptyEntries);
Instead if you want to add a zero when your code meets an empty string then replace the Int32.Parse with Int32.TryParse. This will allow you to check the result of the conversion without getting an exception in case of a missing value
for(.....)
{
int value;
Int32.TryParse(splitedArray[j], out value);
// if conversion fails, value will be set to the default value for integers (0)
provincial[i,j] = value;
}

Find largest number in a double array

I have a double array like this.
double[] arr={1.5,10.9,8.9,6.5,10.0};
How can I want to find out the largest number amoung those array elements
I already have the basic logic
public double getLargest(double[] arrray)
{
double largest = arrray[0];
for (int i = 1; i < arrray.Length;i++ )
{
if (arrray[i] > largest)
largest = arrray[i];
}
return largest;
}
I asked for a method like Math.max(); but Math.max() is not getting even I import System.Linq; (It may be due to the reason that I am using framework 2.0)
Any way I did this method.
You can use Enumerable.Max Method
Returns the maximum value in a sequence of values.
double[] arr = { 1.5, 10.9, 8.9, 6.5, 10.0 };
Console.WriteLine(arr.Max()); //10.9
Here a demonstration.
Assuming your array is named arr
private double Biggest(double[] arr)
{
if(arr != null && arr.Length > 0)
return arr.Max();
return 0;
}
If you want to be more elaborate
private double? Biggest(double[] arr)
{
if(arr != null && arr.Length > 0)
return arr.Max();
return null;
}
Use LINQ, specifically the Enumerable.Max method:
var max = arr.Max();
You need the Enumerable.Max method. It's an extension method, s you can use it like this:
double maximum = arr.Max();
This requires a using System.Linq statement at the top of the file though.
Just to show the "simple" way to do it since I feel that is what the OP should learn first:
double max_value = 0;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max_value)
max_value = arr[i];
}
Basic stuff, no need for fancy methods, max_value contains the maximum value after one pass of the whole array.
You can simply do it using Linq:
double max_number = arr.Max();
To use Ling don't forget to include using System.Linq on top.
double max=0;
foreach (double num in arr)
{
if (num>max) {max=num;}
}

C# Sorting Strings only on first letter

I'm trying to sort a list of strings in alphabetical order in C#. My code looks like this:
public static List<Result> sort(List<Result> listToSort)
{
int listSize = listToSort.Count;
for (int i = 0; i < listSize; i++)
{
for (int j = 0; j < listSize; j++)
{
if (listToSort[i].SN[0] < listToSort[j].SN[0])
{
Result tempValue = listToSort[j];
listToSort[j] = listToSort[i];
listToSort[i] = tempValue;
}
}
}
return listToSort;
}
But it's only sorting it based on the first letter of a string. In other words, if I have a list like this:
donald, abby, dave, bob, sam, pete
It will sort it like so:
abby, bob, donald, dave, pete, sam
One would expect 'dave' to come before 'donald'..
Any ideas?
Currently you are only sorting by the first letter that is why you are seeing this result. You can use Enumerable.OrderBy - LINQ
List<Result> sortedList = listToSort.OrderBy(r=> r.SN).ToList();
Or for your current code you can modify your check to:
if (string.Compare(listToSort[i].SN,listToSort[j].SN) < 0)
How about using LINQ for this:
return listToSort.OrderBy(report => report.SN)
I'm assuming your Report class has a string property you want the list to be sorted by?
EDIT
Didn't notice that you'd already specified the SN property, have amended my answer.
public static List<Result> sort(List<Result> listToSort)
{
return listToSort.OrderBy(x=>x.SN[0]).ToList();
}
You're only ever evaluating the first letter. Try using the traditional sorting method:
public static void Sort(List<Result> listToSort)
{
listToSort.Sort(new ResultComparator());
}
public class ResultComparator : IComparer<Result>
{
public int Compare(Result x, Result y)
{
if (x == null && y == null) return 0;
if (x == null) return 1;
if (y == null) return 0;
// compare based in SN
return string.Compare(x.SN, y.SN);
}
}
Take a look at this part:
for (int i = 0; i < listSize; i++)
{
for (int j = 0; j < listSize; j++)
{
if (listToSort[i].SN[0] < listToSort[j].SN[0])
{
You are
only comparing on SN[0]. If SN is a string then that explains your main result.
always using the same compare, whether i < j or i > j
Best thing to do is to use a built-in sort. Linq's OrderBy(lambda) is the easiest but it creates a new list. For an in-place sort, use List<T>.Sort(Comparer).
If you do have to do it yourself, look up a good sorting algorithm (wikipedia).
It was happened because of comparing character of the first string (listToSort[i].SN[0] => which produces the first character of your input). If you want to compare the string values, you should use string.Compare() method.
--SJ

c# string split and combine

i have a string that conatin 5 numbers like
'1,4,14,32,47'
i want to make from this string 5 strings of 4 number in each one
like :
'1,4,14,32'
'1,4,14,47'
'1,4,32,47'
'1,14,32,47'
'4,14,32,47'
what is the simple/faster way to do it
is the way of convert this to array unset every time diffrent entery and combine
them back to string ?
is there a simple way to do it ?
thanks
How about something like
string s = "1,4,14,32,47";
string r = String.Join(",", s.Split(',').Where((x, index) => index != 1).ToArray());
Using string.Split() you can create a string array. Loop through it, so that in each loop iteration you indicate which element should be skipped (on the first pass, ignore the first element, on the second pass, ignore the second element).
Inside that loop, create a new array that contains all elements but the one you want to skip, then use string.Join() to create each result.
Have a look at:
http://msdn.microsoft.com/en-us/magazine/ee310028.aspx Here you'll find an example in F# who will give the correct background in combinations and permutations (that's how is called what you need). There is code too, I think it's easy to translate it in C#
Example of Code in C# (text in Italian but code in English)
For those who need a more generic algorithm, here is one which gives n length subsets of m items:
private void GetPermutations()
{
int permutationLength = 4;
string s = "1,4,14,32,47";
string[] subS = s.Split(',');
int[] indexS = new int[permutationLength];
List<string> result = new List<string>();
IterateNextPerm(permutationLength, indexS, subS, result);
// Result will hold all your genberated data.
}
private void IterateNextPerm(int permutationLength, int[] pIndexes, string[] subS, List<string> result)
{
int maxIndexValue = subS.Count() - 1;
bool isCorrect = true;
for (int index = 0; index < permutationLength - 1; index++)
{
if (pIndexes[index] >= pIndexes[index + 1])
{
isCorrect = false;
break;
}
}
// Print result if correct
if (isCorrect)
{
string strNewPermutation = string.Empty;
for (int index = 0; index < permutationLength; index++)
{
strNewPermutation += subS[pIndexes[index]] + ",";
}
result.Add(strNewPermutation.TrimEnd(','));
}
// Increase last index position
pIndexes[permutationLength - 1]++;
// Check and fix if it's out of bounds
if (pIndexes[permutationLength - 1] > maxIndexValue)
{
int? lastIndexIncreased = null;
// Step backwards and increase indexes
for (int index = permutationLength - 1; index > 0; index--)
{
if (pIndexes[index] > maxIndexValue)
{
pIndexes[index - 1]++;
lastIndexIncreased = index - 1;
}
}
// Normalize indexes array, to prevent unnecessary steps
if (lastIndexIncreased != null)
{
for (int index = (int)lastIndexIncreased + 1; index <= permutationLength - 1; index++)
{
if (pIndexes[index - 1] + 1 <= maxIndexValue)
{
pIndexes[index] = pIndexes[index - 1] + 1;
}
else
{
pIndexes[index] = maxIndexValue;
}
}
}
}
if (pIndexes[0] < maxIndexValue)
{
IterateNextPerm(permutationLength, pIndexes, subS, result);
}
}
I know that it's not the nicest coding, but I've written it right now in the last half an hour so I'm sure there are things to tweek there.
Have fun coding!
var elements = string.Split(',');
var result =
Enumerable.Range(0,elements.Length)
.Reverse()
.Select(
i=>
string.Join(","
Enumerable.Range(0,i).Concat(Enumerable.Range(i+1,elements.Length - i - 1))
.Select(j=>elements[j]).ToArray() // This .ToArray() is not needed in NET 4
)
).ToArray();
your wording is pretty confusing...but the example is clear enough. just split it on commas, then remove one index, then use string.Join(",", list); to put it back together..

Categories

Resources