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;}
}
Related
int[] array = new int[5]{5,7,8,15,20};
int TargetNumber = 13;
For a target number, I want to find the closest number in an array. For example, when the target number is 13, the closest number to it in the array above is 15. How would I accomplish that programmatically in C#?
EDIT: Have adjusted the queries below to convert to using long arithmetic, so that we avoid overflow issues.
I would probably use MoreLINQ's MinBy method:
var nearest = array.MinBy(x => Math.Abs((long) x - targetNumber));
Or you could just use:
var nearest = array.OrderBy(x => Math.Abs((long) x - targetNumber)).First();
... but that will sort the whole collection, which you really don't need. It won't make much difference for a small array, admittedly... but it just doesn't feel quite right, compared with describing what you're actually trying to do: find the element with the minimum value according to some function.
Note that both of these will fail if the array is empty, so you should check for that first.
If you're using .Net 3.5 or above LINQ can help you here:
var closest = array.OrderBy(v => Math.Abs((long)v - targetNumber)).First();
Alternatively, you could write your own extension method:
public static int ClosestTo(this IEnumerable<int> collection, int target)
{
// NB Method will return int.MaxValue for a sequence containing no elements.
// Apply any defensive coding here as necessary.
var closest = int.MaxValue;
var minDifference = int.MaxValue;
foreach (var element in collection)
{
var difference = Math.Abs((long)element - target);
if (minDifference > difference)
{
minDifference = (int)difference;
closest = element;
}
}
return closest;
}
Useable like so:
var closest = array.ClosestTo(targetNumber);
Both Jon and Rich gave great answers with MinBy and ClosestTo. But I would never recommend using OrderBy if your intent is to find a single element. It's far too inefficient for those kinds of tasks. It's simply the wrong tool for the job.
Here's a technique that performs marginally better than MinBy, is already included in the .NET framework, but less elegant than MinBy: Aggregate
var nearest = array.Aggregate((current, next) => Math.Abs((long)current - targetNumber) < Math.Abs((long)next - targetNumber) ? current : next);
As I said, not as elegant as Jon's method, but viable.
Performance on my computer:
For(each) Loops = fastest
Aggregate = 2.5x slower than loops
MinBy = 3.5x slower than loops
OrderBy = 12x slower than loops
I found this really sexy approach years ago in Math.NET Numerics https://numerics.mathdotnet.com/ which works with BinarySearch in the array. It was a good help in preparation for interpolations and works down to .Net 2.0:
public static int LeftSegmentIndex(double[] array, double t)
{
int index = Array.BinarySearch(array, t);
if (index < 0)
{
index = ~index - 1;
}
return Math.Min(Math.Max(index, 0), array.Length - 2);
}
If you need to find the closest value to the average
very open style
public static double Miidi(double[] list)
{
bool isEmpty = !list.Any();
if (isEmpty)
{
return 0;
}
else
{
double avg = list.Average();
double closest = 100;
double shortest = 100;
{
for ( int i = 0; i < list.Length; i++)
{
double lgth = list[i] - avg;
if (lgth < 0)
{
lgth = lgth - (2 * lgth);
}
else
lgth = list[i] - avg;
if (lgth < shortest)
{
shortest = lgth;
closest = list[i];
}
}
}
return closest;
}
}
Performance wise custom code will be more useful.
public static int FindNearest(int targetNumber, IEnumerable<int> collection) {
var results = collection.ToArray();
int nearestValue;
if (results.Any(ab => ab == targetNumber))
nearestValue = results.FirstOrDefault(i => i == targetNumber);
else{
int greaterThanTarget = 0;
int lessThanTarget = 0;
if (results.Any(ab => ab > targetNumber)) {
greaterThanTarget = results.Where(i => i > targetNumber).Min();
}
if (results.Any(ab => ab < targetNumber)) {
lessThanTarget = results.Where(i => i < targetNumber).Max();
}
if (lessThanTarget == 0) {
nearestValue = greaterThanTarget;
}
else if (greaterThanTarget == 0) {
nearestValue = lessThanTarget;
}
else if (targetNumber - lessThanTarget < greaterThanTarget - targetNumber) {
nearestValue = lessThanTarget;
}
else {
nearestValue = greaterThanTarget;
}
}
return nearestValue;
}
Now, I may get negative points because perhaps somewhere in vast internet there is already an answer to this but I tried to look for it and I simply couldnt find it.
The gist of the problem is that HackerRanks wants you to create an array with a size decided by the user, then have the user add its values (integers) and finally have the program sum its values.
There are plenty of ways to do it and I already know how to but my problem is that I just can't understand Hackerrank's code sample in C# it gave me. I commented the parts I don't understand, which is most of it:
static int simpleArraySum(int n, int[] ar) {
// Complete this function
int sum = 0;
foreach( var item in ar){
sum += item;
}
return sum;
}
static void Main(String[] args) {
//I know what this does
int n = Convert.ToInt32(Console.ReadLine());
//I am lost here, just why create a string array and add the split method?
string[] ar_temp = Console.ReadLine().Split(' ');
//I dont understand here neither, what is it converting? What is the parse for?
int[] ar = Array.ConvertAll(ar_temp,Int32.Parse);
//Why send the n when all you need is the array itself?
int result = simpleArraySum(n, ar);
Console.WriteLine(result);
}
I know some people hate HackerRank, and honestly, I do too but it does gives me some nice ways to test my limited skills in coding with c# and testing my logic. So, if there are better sites that helps you test your logic as a CS please share them with me.
Here is the code I made to solve this problem in Visual Studio but for some stupid reason Hackerrank wont accept it unless I make custom inputs:
//This code can be potentially shorter using the code commented further below.
//For practice's sake, it was made longer.
static int simpleArraySum(int[] arr_temp)
{
int total = 0;
foreach (var item in arr_temp)
{
total += item;
}
return total;
}
static void Main(String[] args)
{
int n = Convert.ToInt32(Console.ReadLine());
int[] arr_temp = new int[n];
for (int i = 0; i < n; i++)
{
arr_temp[i] = Convert.ToInt32(Console.ReadLine());
}
int result = simpleArraySum(arr_temp);
//int result = arr_temp.Sum();
Console.WriteLine(result);
Console.ReadLine();
}
You need to convert to string array since if you're on the main method, all it gets are string values from the argument list. To get the sum then you need to convert the string into a usable number / integer.
I agree that it doesn't make sense to send the first argument n in simpleArraySum because n is simply unused.
as for the part int[] ar = Array.ConvertAll(ar_temp,Int32.Parse); it simply tries to take in all the integers into the array. It is also risky because if you accidentally pass in a string then it will throw an error i.e. pass in "3 4 1 f" <- f will throw an exception, unless this is the desired behaviour.
Personally I think the main method should not be interested in getting involved too much with the data, the heavy lifting should be done in the methods. The better version perhaps would be to modify simpleArraySum and refactor that line in like:
static int simpleArraySum(string input)
{
String[] fields = input.Split(null);
List<int> vals = new List<int>();
foreach (string i in fields)
{
var j = 0;
if (Int32.TryParse(i, out j)) vals.Add(j);
}
int sum = 0;
foreach (var item in vals)
{
sum += item;
}
return sum;
}
I introduced the use of generic list because it's more readable if not cleaner, although the use of List might look overkill to some programmers and might not be as light weight as just using an array, hence on the other hand you can easily stick to using arrays except that it needs to be initialized with the length i.e. int[] vals = new int[fields.Length]; Roughly:
static int simpleArraySum(string input)
{
String[] fields = input.Split(null);
int[] vals = new int[fields.Length];
for (int i = 0; i < fields.Length; i++)
{
var j = 0;
if (Int32.TryParse(fields[i], out j)) vals[i] = j;
}
int sum = 0;
foreach (var item in vals)
{
sum += item;
}
return sum;
}
here my code i hope that helps
static int simpleArraySum(int[] ar,int count) {
if (count > 0 && count <= 10000)
{
if (count == ar.Length)
{
if (!ar.Any(item => (item < 0 || item >= 10000)))
{
return ar.Sum();
}
}
}
return 0;
}
and in main
int arCount = Convert.ToInt32(Console.ReadLine());
int[] arr = Array.ConvertAll(Console.ReadLine().Split(' '), arTemp => Convert.ToInt32(arTemp));
int result = simpleArraySum(arr, arCount);
Console.WriteLine(result);
since Array.ConvertAll() takes a string and convert it to one type array
int or float for example
For users still looking for a 100% C# solution: In above mentioned coding websites do not modify the main function. The aim of the test is to complete the function via the online complier.
using System.Linq;
public static int simpleArraySum(List<int> ar)
{
int sum = ar.Sum();
return sum;
}
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
int[] array = new int[5]{5,7,8,15,20};
int TargetNumber = 13;
For a target number, I want to find the closest number in an array. For example, when the target number is 13, the closest number to it in the array above is 15. How would I accomplish that programmatically in C#?
EDIT: Have adjusted the queries below to convert to using long arithmetic, so that we avoid overflow issues.
I would probably use MoreLINQ's MinBy method:
var nearest = array.MinBy(x => Math.Abs((long) x - targetNumber));
Or you could just use:
var nearest = array.OrderBy(x => Math.Abs((long) x - targetNumber)).First();
... but that will sort the whole collection, which you really don't need. It won't make much difference for a small array, admittedly... but it just doesn't feel quite right, compared with describing what you're actually trying to do: find the element with the minimum value according to some function.
Note that both of these will fail if the array is empty, so you should check for that first.
If you're using .Net 3.5 or above LINQ can help you here:
var closest = array.OrderBy(v => Math.Abs((long)v - targetNumber)).First();
Alternatively, you could write your own extension method:
public static int ClosestTo(this IEnumerable<int> collection, int target)
{
// NB Method will return int.MaxValue for a sequence containing no elements.
// Apply any defensive coding here as necessary.
var closest = int.MaxValue;
var minDifference = int.MaxValue;
foreach (var element in collection)
{
var difference = Math.Abs((long)element - target);
if (minDifference > difference)
{
minDifference = (int)difference;
closest = element;
}
}
return closest;
}
Useable like so:
var closest = array.ClosestTo(targetNumber);
Both Jon and Rich gave great answers with MinBy and ClosestTo. But I would never recommend using OrderBy if your intent is to find a single element. It's far too inefficient for those kinds of tasks. It's simply the wrong tool for the job.
Here's a technique that performs marginally better than MinBy, is already included in the .NET framework, but less elegant than MinBy: Aggregate
var nearest = array.Aggregate((current, next) => Math.Abs((long)current - targetNumber) < Math.Abs((long)next - targetNumber) ? current : next);
As I said, not as elegant as Jon's method, but viable.
Performance on my computer:
For(each) Loops = fastest
Aggregate = 2.5x slower than loops
MinBy = 3.5x slower than loops
OrderBy = 12x slower than loops
I found this really sexy approach years ago in Math.NET Numerics https://numerics.mathdotnet.com/ which works with BinarySearch in the array. It was a good help in preparation for interpolations and works down to .Net 2.0:
public static int LeftSegmentIndex(double[] array, double t)
{
int index = Array.BinarySearch(array, t);
if (index < 0)
{
index = ~index - 1;
}
return Math.Min(Math.Max(index, 0), array.Length - 2);
}
If you need to find the closest value to the average
very open style
public static double Miidi(double[] list)
{
bool isEmpty = !list.Any();
if (isEmpty)
{
return 0;
}
else
{
double avg = list.Average();
double closest = 100;
double shortest = 100;
{
for ( int i = 0; i < list.Length; i++)
{
double lgth = list[i] - avg;
if (lgth < 0)
{
lgth = lgth - (2 * lgth);
}
else
lgth = list[i] - avg;
if (lgth < shortest)
{
shortest = lgth;
closest = list[i];
}
}
}
return closest;
}
}
Performance wise custom code will be more useful.
public static int FindNearest(int targetNumber, IEnumerable<int> collection) {
var results = collection.ToArray();
int nearestValue;
if (results.Any(ab => ab == targetNumber))
nearestValue = results.FirstOrDefault(i => i == targetNumber);
else{
int greaterThanTarget = 0;
int lessThanTarget = 0;
if (results.Any(ab => ab > targetNumber)) {
greaterThanTarget = results.Where(i => i > targetNumber).Min();
}
if (results.Any(ab => ab < targetNumber)) {
lessThanTarget = results.Where(i => i < targetNumber).Max();
}
if (lessThanTarget == 0) {
nearestValue = greaterThanTarget;
}
else if (greaterThanTarget == 0) {
nearestValue = lessThanTarget;
}
else if (targetNumber - lessThanTarget < greaterThanTarget - targetNumber) {
nearestValue = lessThanTarget;
}
else {
nearestValue = greaterThanTarget;
}
}
return nearestValue;
}
Basically comparing a string that is entered, and trying to get that position from the array.
If I initialize position to 0 then it returns the position zero of the array, if I initialize to 1 then it gives me the item in slot 1, so it's skipping the compare statement.
I also tried using (custStatus == cardStatus[i])
public static int discount(string []cardStatus, int []pDiscount, string custStatus)
{
int position= 0;
int discount;
for(int i = 0; i < 2; i++)
{
if (string.Equals(custStatus, cardStatus[i]))
position = i;
}
discount = pDiscount[position];
return discount;
}
With your code, there's no way to tell if position = 0 means custStatus was found in your cardStatus array or if no match was made at all and the default value is being used. I'd recommend either using a boolean matchFound variable or setting position = -1 and adding an extra if statement at the end either way. Either:
boolean matchFound = false;
...
if(matchFound)
{
discount = pDiscount[position];
}
or else
int position = -1;
...
if(position >= 0)
{
discount = pDiscount[position];
}
Give this a try:
public static int discount(string[] cardStatus, int[] pDiscount, string custStatus) {
var position = Array.IndexOf(cardStatus, custStatus);
return (position == -1) ? -1 : pDiscount[position];
}
public static int discount(string []cardStatus, int []pDiscount, string custStatus)
{
for(int i = 0; i < Math.Min(cardStatus.Length, pDiscount.Length); i++)
{
if (string.Equals(custStatus, cardStatus[i]))
{
return pDiscount[i];
}
}
return -1;
}
Don't be afraid to return directly from FOR-loop, it is old-school that teaches to have only one return point from method. You can have as many returns as it helps you to keep your code clean and easy to read.
And perhaps it would be better to use the following expression in for-loop as it will guard you from possible different lengths of arrays:
for (int i = 0; i < Math.Min(cardStatus.Length, pDiscount.Length; i++)
This looks ok, even though this is somewhat more straightforward:
for(int i = 0; i < cardStatus.Length; i++)
{
if (custStatus == cardStatus[i])
{
position = i;
break;
}
}
Given your question it appears to be the case that all cardStatus[i] match custStatus - did you check the input?
Also given your code what happens if there is no match? Currently you would return pDiscount[0] - that doesn't seem to be correct.