locked
How to create a lambda that will find closest number by order? RRS feed

  • Question

  • This text is reedited.

    I try to find in order the closest number from my variable.

    For exemple:

    variable is fib = 1.23

    A list produce a series of numbers: 

    1.22 , 1.26, 1.33, 1.21 , 1.215, 1.225 etc

    The lambda need to find the closest number from 1.23 (1.225) than keep on looking for the next closest number from the previous one. In this case 1.22 which is the closest number from 1.225 than the next one 1.23 which is the closest number from 1.225. 

    I came up with that lambda expression:

    var minDistance = list.Min(no => Math.Abs(fibo- no));
    var closest = list.First(no => Math.Abs(fibo- no) == minDistance);

    but only find the closest from the variable and wont go further.

    Thank you



    • Edited by Frankdot Tuesday, August 27, 2019 11:46 AM clarify
    Monday, August 26, 2019 5:33 PM

All replies

  • Please rephrase your question. Post a concise and complete example, preferably as console application.

    "The values" are calculated "one by one", cause .Net does not parallelize execution. So one value is calculated after the other as the loop continues to increase the barIndex variable.

    Monday, August 26, 2019 6:35 PM
  • Its because after the if statement the prices will pass through a certain number of formulas.

    At the end a lambda expression choose one value (return). 

    My problem is not really that the prices are tested all together its more the lambda expression that chose one value for all the prices. I thought it was possible to get the prices to be process one by one in the if statement so my lambda expression returns a value for each prices.

    When you think about it what i need is my lambda expression to be able to differentiate each prices and get the value for each one. 

    thank you

    Monday, August 26, 2019 6:51 PM
  • Can you please respond to Stefan's request (I would ask the same question as Stefan).

    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Monday, August 26, 2019 7:17 PM
  • Since the code you posted does not include a lambda expression at all, I hope you can understand why everyone here is confused by your question.

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Monday, August 26, 2019 9:41 PM
  • I reedited the text i hope it is less confusing.
    Tuesday, August 27, 2019 11:47 AM
  • hmm..

    Tuesday, August 27, 2019 1:34 PM
  • Still no concise sample..

    namespace ConsoleCS
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
    
        public class Program
        {
            public static void Main(string[] args)
            {
                List<double> numbers = ConstructList();
                numbers.ToConsole<double>("Unsorted");
    
                List<double> sorted = Sort(numbers, 1.23);
                sorted.ToConsole<double>("Sorted");
    
                Console.WriteLine("\nDone.");
                Console.ReadLine();
            }
    
            private static List<double> Sort(List<double> numbers, double pivot)
            {
                List<double> result = new List<double>();
                while (numbers.Count>0)
                {
                    var minDistance = numbers.Min(n => Math.Abs(pivot - n));
                    var closest = numbers.First(n => Math.Abs(pivot - n) == minDistance);
                    numbers.Remove(closest);
                    result.Add(closest);
                }
    
                return result;
            }
    
            private static List<double> ConstructList()
            {
                List<double> result = new List<double>();
                result.Add(1.22);
                result.Add(1.26);
                result.Add(1.33);
                result.Add(1.21);
                result.Add(1.215);
                result.Add(1.225);
                return result;
            }
        }
    }
    
    namespace ConsoleCS
    {
        using System;
        using System.Collections.Generic;
    
        public static class EnumerableHelper
        {
            public static void ToConsole<T>(this IEnumerable<T> enumerable)
            {
                foreach (T item in enumerable)
                {
                    Console.WriteLine(item);
                }
            }
    
            public static void ToConsole<T>(this IEnumerable<T> enumerable, string caption)
            {
                Console.WriteLine(caption);
                foreach (T item in enumerable)
                {
                    Console.WriteLine(item);
                }
    
                Console.WriteLine("");
            }
    
            public static void ToConsole<T>(this IEnumerable<T> enumerable, Func<T, string> toString)
            {
                foreach (T item in enumerable)
                {
                    Console.WriteLine(toString(item));
                }
            }
    
            public static void ToConsole<T>(this IEnumerable<T> enumerable, string caption, Func<T, string> toString)
            {
                Console.WriteLine(caption);
                foreach (T item in enumerable)
                {
                    Console.WriteLine(toString(item));
                }
    
                Console.WriteLine("");
            }
        }
    }
    

    Tuesday, August 27, 2019 1:45 PM
  • Thanks for the effort. You see my list is a union of other lists:

    var list = zlist.Union(alist)
                              .Union(blist)
                              .Union(clist)
                              .Union(dlist)
                     .Union(elist)
                  .Union(flist)
                  .Union(glist)
                  .Union(hlist)
                  .Union(jlist)
                  .Union(klist)
                  .Union(mlist)
                  .Union(nlist)
                  .Union(olist)
                  .Union(plist)
                  .Union(qlist)
                  .Union(rlist)
                  .Union(slist)
                  .Union(zzlist)  
                  .Union(aalist)
                              .Union(bblist)
                              .Union(cclist)
                              .Union(ddlist)
                     .Union(eelist)
                  .Union(fflist)
                  .Union(gglist)
                  .Union(hhlist)
                  .Union(jjlist)
                  .Union(kklist)
                  .Union(mmlist)
                  .Union(nnlist)
                  .Union(oolist)
                  .Union(pplist)
                  .Union(qqlist)
                  .Union(rrlist)
                  .Union(sslist)
                              .ToList();   
              
              double minDistance = list.Min(no => Math.Abs(fibo1- no));
                  closest = list.First(no => Math.Abs(fibo1- no) == minDistance);

    So the number of returns to compare to the variable fib is very large. 

    Console.WriteLine(""); cant be apply because the software is a charting software named ninjatrader and they use Print()

    I was inspired by this thread https://social.msdn.microsoft.com/Forums/en-US/54e0ec6e-319c-438f-a59f-141f7c51e795/how-to-get-the-nearest-one-to-a-given-value-in-a-list-and-the-second-nearest-one-too?forum=csharpgeneral

    I did a little post to ask but the thread is old i dont think they will reply.

    I should of mention those details earlier, my apologize.

    Looks fine to me i just need to find out how to replace all the Console.WriteLine(toString(item)); for Print.


    • Edited by Frankdot Tuesday, August 27, 2019 2:03 PM tested but need modification
    Tuesday, August 27, 2019 1:56 PM
  • Thanks for the effort. You see my list is a union of other lists:[..]

    So the number of returns to compare to the variable fib is very large.

    This does not matter for an abstract solution of a problem per se. It is an indicator that a runtime (Big-O) analyisis maybe necessary.

    Console.WriteLine(""); cant be apply because the software is a charting software named ninjatrader and they use Print()

    While it is often important to undestand the context of problem, it is not important nor an restriction for an abstract solution. Especially that you need to craft a concise and complete example for analyzing your problem and implmenting a solution.

    Using a console application is normally one of two ways to do it properly. The other way is using unit test. Here you would start by writing unit test for your problem, then implementing the solutino into your logic class.

    And for discussing such problems in forms, using a console application is the primary choice, cause in most situations it is the most concise one. No clutter like forms or components or dependencies hiding something.

    Just create your list as needed in the ConstructList() method. E.g. serialize some test data from your application to XML and load it there.

    Wednesday, August 28, 2019 10:42 AM
  • Thanks for replying.

    It's not just the Print() issue, that part has been resolved. 

    Anything that is currently static needs to be made non-static. Also  NinjaScript does not use static variables because its already inside a class.

    The way i see it every numbers.Min should be replace by list. and pivot is replaced by fibo1 my variable (1.23) that is a dynamic variable that change in time.

    This part of the code:

    List<double> sorted = Sort(numbers, 1.23);
    sorted.ToConsole<double>("Sorted");

    bugs me, it is important but i dont get how it fit in the structure. Also the last part:

    public static class EnumerableHelper
    {
    public static void ToConsole<T>(this IEnumerable<T> enumerable)
    {
    foreach (T item in enumerable)
    {
    Console.WriteLine(item);
    }
    }
    public static void ToConsole<T>(this IEnumerable<T> enumerable, string caption)
    {
    Console.WriteLine(caption);
    foreach (T item in enumerable)
    {
    Console.WriteLine(item);
    }

    Console.WriteLine("");
    }

    I need to read more on  IEnumerable<T> to understand how that part is necessary to run the code.

    That deals with concept i dont master yet. 

    That makes my questions evasive and unproductive.

    Its been 3 months i am learning c# by myself so you will understand why i have so many interrogations.

     


    • Edited by Frankdot Wednesday, August 28, 2019 12:27 PM
    Wednesday, August 28, 2019 12:26 PM
  • The helper belongs to a separate file. It's my generic method to output the content of any IEnumerable like lists or generic lists to the console without always coding a loop for it.

    Thus ignore the internals of it.

    Just look at what List<double> sorted = Sort(numbers, 1.23); does internally. Cause here you need to implement your functionality.

    In my example I implemented what I think you mean by your descriptions. When you did not got it to run so far, this is its output:

    btw, this would be equal to a sort by distance to your pivot element:

    namespace ConsoleCS
    {
        using System;
        using System.Collections.Generic;
    
        public class Program
        {
            public static void Main(string[] args)
            {
                double pivot = 1.23;
    
                List<double> numbers = ConstructList();
                numbers.ToConsole<double>("Unsorted");
                numbers.Sort(Comparer<double>.Create((x, y) => Math.Abs(pivot - x) < Math.Abs(pivot-y) ? -1 : Math.Abs(pivot - x) > Math.Abs(pivot - y) ? 1 : 0));
                numbers.ToConsole<double>("Sorted");
    
                Console.WriteLine("\nDone.");
                Console.ReadLine();
            }
    
            private static List<double> ConstructList()
            {
                List<double> result = new List<double>();
                result.Add(1.22);
                result.Add(1.26);
                result.Add(1.33);
                result.Add(1.21);
                result.Add(1.215);
                result.Add(1.225);
                return result;
            }
        }
    }


    Wednesday, August 28, 2019 12:54 PM
  • I did test it on https://dotnetfiddle.net/ and it return the same as your output black window.

    That's why i said in earlier post looks fine to me i just need to find out how to replace what is related to C# console program.

    For the moment i came up with that but that's not working obviously. There are a bunch of errors:

    double pivot = fibo1;
                       List<double> numbers = new List<double>() {list};
                       numbers.ToConsole<double>("Unsorted");
                       numbers.Sort(Comparer<double>.Create((x, y) => Math.Abs(pivot - x) < Math.Abs(pivot-y) ? -1 : Math.Abs(pivot - x) > Math.Abs(pivot - y) ? 1 : 0));
                       numbers.ToConsole<double>("Sorted");

                       Console.WriteLine("\nDone.");
                       Console.ReadLine();

    NinjaScript File Error Code Line Column
    SampleDisplayBarsAgo.cs Overloaded Add method 'System.Collections.Generic.List <double> .Add (double)' best matching collection initializer has invalid arguments CS1950 628 63

    Argument 1: Unable to convert from 'System.Collections.Generic.List <double>' to 'double

    System.Collections.Generic.List <double> 'does not contain a definition for' ToConsole 'and no' ToConsole 'extension method that accepts a first argument of type' System.Collections.Generic.List <double> 'was found (a using directive or an assembly reference is missing?)

    The code is doing what it is suppose to do, it just need to be converted to ninjascipt. 

    Actually if you input that code: it will return a compiling error: (the one from the previous post (according to https://dotnetfiddle.net/)

    Compilation error (line 13, col 21): 'System.Collections.Generic.List<double>' does not contain a definition for 'ToConsole' and no extension method 'ToConsole' accepting a first argument of type 'System.Collections.Generic.List<double>' could be found (are you missing a using directive or an assembly reference?

    if i try:

    double pivot = fibo1;
                              
                              
                               list.Sort(Comparer<double>.Create((x, y) => Math.Abs(pivot - x) < Math.Abs(pivot-y) ? -1 : Math.Abs(pivot - x) > Math.Abs(pivot - y) ? 1 : 0));
                              
               Print(list);

    i get that error:
    System.Collections.Generic.List`1[System.Double]

    thank you



    • Edited by Frankdot Wednesday, August 28, 2019 5:40 PM
    Wednesday, August 28, 2019 5:20 PM