How to find common smallest number in two arrays - c#

I have two arrays that I need to sort and find the lowest number that occurs in both arrays. If there is no equality then it should return -1, if there is equality then it should return that number.
Here is my the code I have got so far
public int solution(int[] A, int[] B)
{
int minA = A.Min();// Get minimum number of array A
int minB = B.Min();// Get minimum number of array B
if (minA == minB)// If both arrays have the same smallest number
return minA;
else
return -1;
}
The problem is it is only checking for equality of the lowest number and if it does not match then it returns. How do I get it to look at the next lowest number?

I think you are trying to get the common minimum number (Intersection). So you can use Intersect in this case.
int[] arrA = {100, 102, 99, 107};
int[] arrB = {103, 102, 99, 105, 106, 109};
var commonNumbers = arrA.Intersect(arrB).ToArray();
return commonNumbers.Any() ? commonNumbers.Min() : -1);

I think the best way to approach this problem is to sort the array first, you should try:
public int solution(int[] A, int[] B)
{
//Sorts the array
Array.Sort(A)
Array.Sort(B)
//store the array positions
int j = 0;
int i = 0;
While(i < Array.Length(A) && j < Array.Length(B)) //If any array ends before finding the equality, the while ends and the code return -1;
{
if(A[i] == B[j])
{
return A[i];
}
//if the element from A is larger than the element from B, you have to go up an element in B
if(A[i] > B[j])
{
j++;
}
//if the element from B is larger than the element from A, you have to go up an element in A
if(A[i] < B[j])
{
i++;
}
}
return -1;
}
I didn't tested, but think it should work.

You may try this:
public int solution(int[] A, int[] B)
{
var common = A.Intersect(B).ToList();
return common.Count > 0 ? common.Min() : -1;
}

In pseudocode:
sort array A in ascending order
sort array B in ascending order
set elementB to the first element in B
for all elements in A
if (elementA == elementB)
return elementA
while (elementA > elementB)
try to get the next element from B
if there are no more elements in B
return -1
if (elementA == elementB)
return elementA
end while
// elementA is less than elementB
end for
return -1
In English:
Go through the A list and compare each value with the current value in B. If they match, we're done.
If the value in B is smaller than A, then get the next value from B (because the numbers are sorted from small to large, there will never be a B value that matches the current A).
Keep grabbing the next B value until it is equal to A (we're done) or it is bigger than A (we need to grab the next A value to see if it catches up with the new B).
If we hit the end of either list, there are no matches.

The problem is search the both pre-minimum and then compare, this solution is without pre-sorting, optimizing CPU and memory:
public int solution(int[] A, int[] B)
{
//NOTE: Assumption that the array contains at least 2 values, check & handle the different cases properly
//Take the first 2 values in order
if(A[0]<A[1]){
minA=A[0];
minA2=A[1];
}else{
minA=A[1];
minA2=A[0];
}
//Take the first 2 values in order
if(B[0]<B[1]){
minB=B[0];
minB2=B[1];
}else{
minB=B[1];
minB2=B[0];
}
//Select the minimum and second minimum of A
for(int i=0;i<A.Length;i++){
if(minA>=A[i]){
minA2=minA;//The previous minimum become the second minimum
minA=A[i];
}else if(minA2>A[i]){
minA2=A[i];//A[i] is the actual second minimum
}
}
//Select the minimum and second minimum of B
for(int i=0;i<B.Length;i++){
if(minB>=B[i]){
minB2=minB;//The previous minimum become the second minimum
minB=A[i];
}else if(minB2>B[i]){
minB2=B[i];//B[i] is the actual second minimum
}
}
//Do your comparison
return (minA==minB&&minA2==minB2)?minB2:-1;
//NOTE: if you want to check only the second lower: return minA2==minB2?minB2:-1;
}

Here is my solution in python.
#Solution 1
def solution(A, B):
commonList = [n for n in B if n in A]
commonList.sort()
if len(commonList) > 0:
return commonList[0]
return -1
#Solution 2
def solution(A, B):
commonList = []
for n in A: #Iterates through A and check the elements that appear in B
if n in B:
commonList.append(n)
commonList.sort()
#Sort list in order to get minimum value in the first index.
#you could use min(commonList) too
if len(commonList) > 0:
return commonList[0]
return -1

Related

How to Order By or Sort an integer List and select the Nth element

I have a list, and I want to select the fifth highest element from it:
List<int> list = new List<int>();
list.Add(2);
list.Add(18);
list.Add(21);
list.Add(10);
list.Add(20);
list.Add(80);
list.Add(23);
list.Add(81);
list.Add(27);
list.Add(85);
But OrderbyDescending is not working for this int list...
int fifth = list.OrderByDescending(x => x).Skip(4).First();
Depending on the severity of the list not having more than 5 elements you have 2 options.
If the list never should be over 5 i would catch it as an exception:
int fifth;
try
{
fifth = list.OrderByDescending(x => x).ElementAt(4);
}
catch (ArgumentOutOfRangeException)
{
//Handle the exception
}
If you expect that it will be less than 5 elements then you could leave it as default and check it for that.
int fifth = list.OrderByDescending(x => x).ElementAtOrDefault(4);
if (fifth == 0)
{
//handle default
}
This is still some what flawed because you could end up having the fifth element being 0. This can be solved by typecasting the list into a list of nullable ints at before the linq:
var newList = list.Select(i => (int?)i).ToList();
int? fifth = newList.OrderByDescending(x => x).ElementAtOrDefault(4);
if (fifth == null)
{
//handle default
}
Without LINQ expressions:
int result;
if(list != null && list.Count >= 5)
{
list.Sort();
result = list[list.Count - 5];
}
else // define behavior when list is null OR has less than 5 elements
This has a better performance compared to LINQ expressions, although the LINQ solutions presented in my second answer are comfortable and reliable.
In case you need extreme performance for a huge List of integers, I'd recommend a more specialized algorithm, like in Matthew Watson's answer.
Attention: The List gets modified when the Sort() method is called. If you don't want that, you must work with a copy of your list, like this:
List<int> copy = new List<int>(original);
List<int> copy = original.ToList();
The easiest way to do this is to just sort the data and take N items from the front. This is the recommended way for small data sets - anything more complicated is just not worth it otherwise.
However, for large data sets it can be a lot quicker to do what's known as a Partial Sort.
There are two main ways to do this: Use a heap, or use a specialised quicksort.
The article I linked describes how to use a heap. I shall present a partial sort below:
public static IList<T> PartialSort<T>(IList<T> data, int k) where T : IComparable<T>
{
int start = 0;
int end = data.Count - 1;
while (end > start)
{
var index = partition(data, start, end);
var rank = index + 1;
if (rank >= k)
{
end = index - 1;
}
else if ((index - start) > (end - index))
{
quickSort(data, index + 1, end);
end = index - 1;
}
else
{
quickSort(data, start, index - 1);
start = index + 1;
}
}
return data;
}
static int partition<T>(IList<T> lst, int start, int end) where T : IComparable<T>
{
T x = lst[start];
int i = start;
for (int j = start + 1; j <= end; j++)
{
if (lst[j].CompareTo(x) < 0) // Or "> 0" to reverse sort order.
{
i = i + 1;
swap(lst, i, j);
}
}
swap(lst, start, i);
return i;
}
static void swap<T>(IList<T> lst, int p, int q)
{
T temp = lst[p];
lst[p] = lst[q];
lst[q] = temp;
}
static void quickSort<T>(IList<T> lst, int start, int end) where T : IComparable<T>
{
if (start >= end)
return;
int index = partition(lst, start, end);
quickSort(lst, start, index - 1);
quickSort(lst, index + 1, end);
}
Then to access the 5th largest element in a list you could do this:
PartialSort(list, 5);
Console.WriteLine(list[4]);
For large data sets, a partial sort can be significantly faster than a full sort.
Addendum
See here for another (probably better) solution that uses a QuickSelect algorithm.
This LINQ approach retrieves the 5th biggest element OR throws an exception WHEN the list is null or contains less than 5 elements:
int fifth = list?.Count >= 5 ?
list.OrderByDescending(x => x).Take(5).Last() :
throw new Exception("list is null OR has not enough elements");
This one retrieves the 5th biggest element OR null WHEN the list is null or contains less than 5 elements:
int? fifth = list?.Count >= 5 ?
list.OrderByDescending(x => x).Take(5).Last() :
default(int?);
if(fifth == null) // define behavior
This one retrieves the 5th biggest element OR the smallest element WHEN the list contains less than 5 elements:
if(list == null || list.Count <= 0)
throw new Exception("Unable to retrieve Nth biggest element");
int fifth = list.OrderByDescending(x => x).Take(5).Last();
All these solutions are reliable, they should NEVER throw "unexpected" exceptions.
PS: I'm using .NET 4.7 in this answer.
Here there is a C# implementation of the QuickSelect algorithm to select the nth element in an unordered IList<>.
You have to put all the code contained in that page in a static class, like:
public static class QuickHelpers
{
// Put the code here
}
Given that "library" (in truth a big fat block of code), then you can:
int resA = list.QuickSelect(2, (x, y) => Comparer<int>.Default.Compare(y, x));
int resB = list.QuickSelect(list.Count - 1 - 2);
Now... Normally the QuickSelect would select the nth lowest element. We reverse it in two ways:
For resA we create a reverse comparer based on the default int comparer. We do this by reversing the parameters of the Compare method. Note that the index is 0 based. So there is a 0th, 1th, 2th and so on.
For resB we use the fact that the 0th element is the list-1 th element in the reverse order. So we count from the back. The highest element would be the list.Count - 1 in an ordered list, the next one list.Count - 1 - 1, then list.Count - 1 - 2 and so on
Theorically using Quicksort should be better than ordering the list and then picking the nth element, because ordering a list is on average a O(NlogN) operation and picking the nth element is then a O(1) operation, so the composite is O(NlogN) operation, while QuickSelect is on average a O(N) operation. Clearly there is a but. The O notation doesn't show the k factor... So a O(k1 * NlogN) with a small k1 could be better than a O(k2 * N) with a big k2. Only multiple real life benchmarks can tell us (you) what is better, and it depends on the size of the collection.
A small note about the algorithm:
As with quicksort, quickselect is generally implemented as an in-place algorithm, and beyond selecting the k'th element, it also partially sorts the data. See selection algorithm for further discussion of the connection with sorting.
So it modifies the ordering of the original list.

Get all possible distinct triples using LINQ

I have a List contains these values: {1, 2, 3, 4, 5, 6, 7}. And I want to be able to retrieve unique combination of three. The result should be like this:
{1,2,3}
{1,2,4}
{1,2,5}
{1,2,6}
{1,2,7}
{2,3,4}
{2,3,5}
{2,3,6}
{2,3,7}
{3,4,5}
{3,4,6}
{3,4,7}
{3,4,1}
{4,5,6}
{4,5,7}
{4,5,1}
{4,5,2}
{5,6,7}
{5,6,1}
{5,6,2}
{5,6,3}
I already have 2 for loops that able to do this:
for (int first = 0; first < test.Count - 2; first++)
{
int second = first + 1;
for (int offset = 1; offset < test.Count; offset++)
{
int third = (second + offset)%test.Count;
if(Math.Abs(first - third) < 2)
continue;
List<int> temp = new List<int>();
temp .Add(test[first]);
temp .Add(test[second]);
temp .Add(test[third]);
result.Add(temp );
}
}
But since I'm learning LINQ, I wonder if there is a smarter way to do this?
UPDATE: I used this question as the subject of a series of articles starting here; I'll go through two slightly different algorithms in that series. Thanks for the great question!
The two solutions posted so far are correct but inefficient for the cases where the numbers get large. The solutions posted so far use the algorithm: first enumerate all the possibilities:
{1, 1, 1 }
{1, 1, 2 },
{1, 1, 3 },
...
{7, 7, 7}
And while doing so, filter out any where the second is not larger than the first, and the third is not larger than the second. This performs 7 x 7 x 7 filtering operations, which is not that many, but if you were trying to get, say, permutations of ten elements from thirty, that's 30 x 30 x 30 x 30 x 30 x 30 x 30 x 30 x 30 x 30, which is rather a lot. You can do better than that.
I would solve this problem as follows. First, produce a data structure which is an efficient immutable set. Let me be very clear what an immutable set is, because you are likely not familiar with them. You normally think of a set as something you add items and remove items from. An immutable set has an Add operation but it does not change the set; it gives you back a new set which has the added item. The same for removal.
Here is an implementation of an immutable set where the elements are integers from 0 to 31:
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System;
// A super-cheap immutable set of integers from 0 to 31 ;
// just a convenient wrapper around bit operations on an int.
internal struct BitSet : IEnumerable<int>
{
public static BitSet Empty { get { return default(BitSet); } }
private readonly int bits;
private BitSet(int bits) { this.bits = bits; }
public bool Contains(int item)
{
Debug.Assert(0 <= item && item <= 31);
return (bits & (1 << item)) != 0;
}
public BitSet Add(int item)
{
Debug.Assert(0 <= item && item <= 31);
return new BitSet(this.bits | (1 << item));
}
public BitSet Remove(int item)
{
Debug.Assert(0 <= item && item <= 31);
return new BitSet(this.bits & ~(1 << item));
}
IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
public IEnumerator<int> GetEnumerator()
{
for(int item = 0; item < 32; ++item)
if (this.Contains(item))
yield return item;
}
public override string ToString()
{
return string.Join(",", this);
}
}
Read this code carefully to understand how it works. Again, always remember that adding an element to this set does not change the set. It produces a new set that has the added item.
OK, now that we've got that, let's consider a more efficient algorithm for producing your permutations.
We will solve the problem recursively. A recursive solution always has the same structure:
Can we solve a trivial problem? If so, solve it.
If not, break the problem down into a number of smaller problems and solve each one.
Let's start with the trivial problems.
Suppose you have a set and you wish to choose zero items from it. The answer is clear: there is only one possible permutation with zero elements, and that is the empty set.
Suppose you have a set with n elements in it and you want to choose more than n elements. Clearly there is no solution, not even the empty set.
We have now taken care of the cases where the set is empty or the number of elements chosen is more than the number of elements total, so we must be choosing at least one thing from a set that has at least one thing.
Of the possible permutations, some of them have the first element in them and some of them do not. Find all the ones that have the first element in them and yield them. We do this by recursing to choose one fewer elements on the set that is missing the first element.
The ones that do not have the first element in them we find by enumerating the permutations of the set without the first element.
static class Extensions
{
public static IEnumerable<BitSet> Choose(this BitSet b, int choose)
{
if (choose < 0) throw new InvalidOperationException();
if (choose == 0)
{
// Choosing zero elements from any set gives the empty set.
yield return BitSet.Empty;
}
else if (b.Count() >= choose)
{
// We are choosing at least one element from a set that has
// a first element. Get the first element, and the set
// lacking the first element.
int first = b.First();
BitSet rest = b.Remove(first);
// These are the permutations that contain the first element:
foreach(BitSet r in rest.Choose(choose-1))
yield return r.Add(first);
// These are the permutations that do not contain the first element:
foreach(BitSet r in rest.Choose(choose))
yield return r;
}
}
}
Now we can ask the question that you need the answer to:
class Program
{
static void Main()
{
BitSet b = BitSet.Empty.Add(1).Add(2).Add(3).Add(4).Add(5).Add(6).Add(7);
foreach(BitSet result in b.Choose(3))
Console.WriteLine(result);
}
}
And we're done. We have generated only as many sequences as we actually need. (Though we have done a lot of set operations to get there, but set operations are cheap.) The point here is that understanding how this algorithm works is extremely instructive. Recursive programming on immutable structures is a powerful tool that many professional programmers do not have in their toolbox.
You can do it like this:
var data = Enumerable.Range(1, 7);
var r = from a in data
from b in data
from c in data
where a < b && b < c
select new {a, b, c};
foreach (var x in r) {
Console.WriteLine("{0} {1} {2}", x.a, x.b, x.c);
}
Demo.
Edit: Thanks Eric Lippert for simplifying the answer!
var ints = new int[] { 1, 2, 3, 4, 5, 6, 7 };
var permutations = ints.SelectMany(a => ints.Where(b => (b > a)).
SelectMany(b => ints.Where(c => (c > b)).
Select(c => new { a = a, b = b, c = c })));

How to return all combinations that contains a given *partial* combination?

I have this c# class that calculates n choose k and then generates all possible combination in lexicographical order. It can also return each combination's order number, e.g: passing [1,2,3,4,5] would return 1 given n choose k(30,5), and 142506 for [26,27,28,29,30].
Is there a way to return all order numbers containing a partial combination? So if I pass [1,2,3,4] it would return: 1,2,3,...25,26.
1: [1,2,3,4,5]
2: [1,2,3,4,6]
3: [1,2,3,4,7]
...
25: [1,2,3,4,29]
26: [1,2,3,4,30]
I need this for a lottery draw. I want each ticket to have it's combination's order number and I need to display the total of possible winners as each of the 5 balls are drawn. Right now each ticket has the actual combination and I run a query to get partial winners but I want to optimize this proccess.
What you need is a function that, for a combination [a, b, c, d, e], returns that combination's order number. Then you can get the combination set for (the set of possible numbers minus the numbers already picked) choose (the number of picks you have yet to make), add in the numbers already picked to each combination, reorder each combination, and use that function to get the order number.
EDIT: This might help: saliu.com/bbs/messages/348.html
EDIT2: And the answer is here: How to calculate the index (lexicographical order) when the combination is given
EDIT3: I took a stab at some C# code for this:
private IEnumerable<int[]> CombinationsFor(int n, int k);
private int CombinationsCount(int n, int k);
private int IndexFor(int n, int[] combination)
{
int k = combination.Count();
int ret = 0;
int j = 0;
for (int i = 0; i < k; i++)
{
for (j++; j < combination[i]; j++)
{
ret += CombinationsCount(n - j, k - i - 1);
}
}
return ret;
}
private IEnumerable<int> PossibleCombinations(int n, int k, int[] picked)
{
int m = picked.Count();
int[] reverseMapping = Enumerable.Range(0, n)
.Where(i=>!picked.Contains(i))
.ToArray();
return CombinationsFor(n-m, k-m)
.Select(c => c
.Select(x=>reverseMapping[x])
.Concat(picked)
.OrderBy(x=>x)
.ToArray()
)
.Select(c => IndexFor(n, c));
}
The combinations you need are (n-d) choose (k-d) where d is the number of fixed draws.
When you generate them they won't have the correct numbers (they are skipping the last d numbers instead of the ones you want) but just reword your combinations using the reverse order mapping of your sublist:
(in pseudo-python-code, as this isn't related to C# at all)
listing = [1, 2, ..., 30]
partial = [4, 7, 25]
draw_size = 5
remaining = listing - partial
reverse_order_mapping = [(index, item) in remaining.items_and_indexes]
n = listing.size // 30
k = draw_size // 5
d = partial.size // 3
for comb in ((n-d) choose (k-d))
actual_comb = comb.map(reverse_order_mapping)
print actual_comb
end
Then you just call your function with the resulting combination(s) (after sorting it if needed).

First Element as pivot in Quick sort

Why this code gives me wrong ? In Quick sort , I have picked up the first element as pivot:
I have traced that on paper,nothing is wrong.
private void QuickSort(ref int [] S ,int l,int h)
{
//partioning
int pivot_index = l;
int j = 0;
int temp = 0;
for(int i=l+1;i<=h;i++)
if (S[pivot_index] > S[i])
{
j++;
temp = S[i];
S[i] = S[j];
S[j] = temp;
}
pivot_index = j;
temp = S[l];
S[l] = S[j];
S[j] = temp;
//end partioning
if (l < h && pivot_index>l && pivot_index<h)
{
QuickSort(ref S, l, pivot_index - 1);
QuickSort(ref S, pivot_index + 1, h);
}
}
here is my main :
int[] List = get_input(textBox1.Text, ref n);
//
QuickSort(ref List, 0, n-1);
Your function is apparently supposed to sort [l, h] range in the array, yet for some reason you are swapping element number i with element number j. The latter (j) is out of [l, h] range (it is always initially 0 and then it becomes 1, 2, 3 and so on). What are you trying to do by this? Why are you swapping your elements to some totally unrelated remote location out of your sorting range?
In other words this does not even remotely look like a QuickSort-style sorting algorithm to me. Your unexplainable manipulations with j is one reason why your implementation cannot really sort anything.
Your algorithm is wrong. Get the pivot value int pivot = S[pivot_index];.
Then determine the two elements that you want to swap. Therefore, determine the first element from the left, which is greater than or equal to the pivot value. This gives i. Then determine the first element from the right, which is less than or equal to the pivot value. This gives j. As long as i is less than j swap S[i] and S[j] and repeat the process.
Only after there are no more swaps to make, look if you can call QuickSort recursively. Here two separate if checks must be made for the left part and the right part.
Also, note that it is better to take the element in the middle as pivot element. QuickSort will perform better, if the elements should be pre-sorted or sorted in descending order.
int pivot = S[(l+h)/2];

Find the closest number in a list of numbers

I have a list of constant numbers. I need to find the closest number to x in the list of the numbers. Any ideas on how to implement this algorithm?
Well, you cannot do this faster than O(N) because you have to check all numbers to be sure you have the closest one. That said, why not use a simple variation on finding the minimum, looking for the one with the minimum absolute difference with x?
If you can say the list is ordered from the beginning (and it allows random-access, like an array), then a better approach is to use a binary search. When you end the search at index i (without finding x), just pick the best out of that element and its neighbors.
I suppose that the array is unordered. In ordered it can be faster
I think that the simpliest and the fastest method is using linear algorithm for finding minimum or maximum but instead of comparing values you will compare absolute value of difference between this and needle.
In the C++ ( I can't C# but it will be similar ) can code look like this:
// array of numbers is haystack
// length is length of array
// needle is number which you are looking for ( or compare with )
int closest = haystack[0];
for ( int i = 0; i < length; ++i ) {
if ( abs( haystack[ i ] - needle ) < abs( closest - needle ) ) closest = haystack[i];
}
return closest;
In general people on this site won't do your homework for you. Since you didn't post code I won't post code either. However, here's one possible approach.
Loop through the list, subtracting the number in the list from x. Take the absolute value of this difference and compare it to the best previous result you've gotten and, if the current difference is less than the best previous result, save the current number from the list. At the end of the loop you'll have your answer.
private int? FindClosest(IEnumerable<int> numbers, int x)
{
return
(from number in numbers
let difference = Math.Abs(number - x)
orderby difference, Math.Abs(number), number descending
select (int?) number)
.FirstOrDefault();
}
Null means there was no closest number. If there are two numbers with the same difference, it will choose the one closest to zero. If two numbers are the same distance from zero, the positive number will be chosen.
Edit in response to Eric's comment:
Here is a version which has the same semantics, but uses the Min operator. It requires an implementation of IComparable<> so we can use Min while preserving the number that goes with each distance. I also made it an extension method for ease-of-use:
public static int? FindClosestTo(this IEnumerable<int> numbers, int targetNumber)
{
var minimumDistance = numbers
.Select(number => new NumberDistance(targetNumber, number))
.Min();
return minimumDistance == null ? (int?) null : minimumDistance.Number;
}
private class NumberDistance : IComparable<NumberDistance>
{
internal NumberDistance(int targetNumber, int number)
{
this.Number = number;
this.Distance = Math.Abs(targetNumber - number);
}
internal int Number { get; private set; }
internal int Distance { get; private set; }
public int CompareTo(NumberDistance other)
{
var comparison = this.Distance.CompareTo(other.Distance);
if(comparison == 0)
{
// When they have the same distance, pick the number closest to zero
comparison = Math.Abs(this.Number).CompareTo(Math.Abs(other.Number));
if(comparison == 0)
{
// When they are the same distance from zero, pick the positive number
comparison = this.Number.CompareTo(other.Number);
}
}
return comparison;
}
}
It can be done using SortedList:
Blog post on finding closest number
If the complexity you're looking for counts only the searching the complexity is O(log(n)). The list building will cost O(n*log(n))
If you're going to insert item to the list much more times than you're going to query it for the closest number then the best choice is to use List and use naive algorithm to query it for the closest number. Each search will cost O(n) but time to insert will be reduced to O(n).
General complexity: If the collection has n numbers and searched q times -
List: O(n+q*n)
Sorted List: O(n*log(n)+q*log(n))
Meaning, from some q the sorted list will provide better complexity.
Being lazy I have not check this but shouldn't this work
private int FindClosest(IEnumerable<int> numbers, int x)
{
return
numbers.Aggregate((r,n) => Math.Abs(r-x) > Math.Abs(n-x) ? n
: Math.Abs(r-x) < Math.Abs(n-x) ? r
: r < x ? n : r);
}
Haskell:
import Data.List (minimumBy)
import Data.Ord (comparing)
findClosest :: (Num a, Ord a) => a -> [a] -> Maybe a
findClosest _ [] = Nothing
findClosest n xs = Just $ minimumBy (comparing $ abs . (+ n)) xs
Performance wise custom code will be more use full.
List<int> results;
int targetNumber = 0;
int nearestValue=0;
if (results.Any(ab => ab == targetNumber ))
{
nearestValue= results.FirstOrDefault<int>(i => i == targetNumber );
}
else
{
int greaterThanTarget = 0;
int lessThanTarget = 0;
if (results.Any(ab => ab > targetNumber ))
{
greaterThanTarget = results.Where<int>(i => i > targetNumber ).Min();
}
if (results.Any(ab => ab < targetNumber ))
{
lessThanTarget = results.Where<int>(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;
}
}

Categories

Resources