none
How to find multiple numbers in a list and test the number again? RRS feed

  • Question

  • Hello,

    double find = 0;
    				
    var listQ = new List<double>() {1,3,3.2,4,4.1,5};
    				
    double i = 3.5;
    				
    find = listQ.Aggregate((x, y) => Math.Abs(x - i) < Math.Abs(y - i) ? x : y);
    				
    				
    				
    Print("item"+find);
    
    // find will return 3.2
    //now i want to find the closest number from 3.2
    // that would be 3 ...
    
    Is there a method allowing me to do that? So that the variable i always = find? The result from find must take the place of i. 

    Thank you

    Wednesday, September 23, 2020 12:53 PM

All replies

  • If you want to repeat it one time, then maybe execute this fragment after your code:

    i = find;

    find = listQ.Where(x => x != i ).Aggregate((x, y) => Math.Abs(x - i) < Math.Abs(y - i) ? x : y);

    Wednesday, September 23, 2020 3:31 PM
  • it will only return one value. The first one.

    It need to store the first result in a new list and than search for the next closest number from find and store the second number in the list, etc.

    Wednesday, September 23, 2020 3:54 PM
  • Hi Frankdot,

    Thank you for posting here.

    I have a question. When the program reaches 3, what should be the next one, 3.2 or 4? In other words, whether the number that has been output needs to be removed.

    I guess the next result should be 4.

    Based on this guess, we can use recursion to solve the problem.

            public static void GetClosest(double num,List<double> listQ)
            {
                if (listQ.Count==0) return;
                double find = 0;
                find = listQ.Aggregate((x, y) => Math.Abs(x - num) < Math.Abs(y - num) ? x : y);
                Console.WriteLine("item: " + find);
                listQ.Remove(find);
                GetClosest(find, listQ);
            }

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, September 24, 2020 2:02 AM
  • Hello Timon,

    Thank you for answering.

    This is a theorical example i created to find a solution for a wider code.

    Imagine instead there is in the list only one number 3.2.

    i = 3.5

    Of course, find will return 3.2

    Now i = 3.2

    Now imagine the List T is renewing all the time and a new number take its place 4.5 instead of 3.2.

    now find = 4.5 

    i send 4.5 to i but keep 3.2 in a newlist. 

    Meaning found = newlist {3.2 , 4.5, ...} everytime new numbers is added in the listQ the value of found is redirected to i and the multiple values of found is added in a newlist.

    I hope this example is easier to understand .

    Frank

    Thursday, September 24, 2020 2:32 PM
  • Hi Frank,

    So the key to the question is how is the list updated?

    I think there should be an event to detect the update of the list. When this event is triggered, can it just call the method?

    In this case, there is no need to use recursion, just use the linq statement.

    Just like the following example, whenever you click the button, it means the list is updated.

        public partial class Form1 : Form
        {
            public BindingList<double> Result { get; set; }
            public BindingList<double> Data { get; set; }
            public double Num { get; set; }
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                Result = new BindingList<double>();
                Data = new BindingList<double>();
                Num = 3.2;
    
                listBox1.DataSource = Data;
                listBox2.DataSource = Result;
                textBox1.Text = Num.ToString(); 
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                textBox1.Text = Num.ToString();
                Data.Clear();
                Random random = new Random();
                for (int i = 0; i < 3; i++)
                {
                    Data.Add(random.NextDouble(1, 10));
                }
                Num = GetClosest(Num, Data);
            }
            public  double GetClosest(double num, BindingList<double> listQ)
            {
                double find = 0;
                find = listQ.Aggregate((x, y) => Math.Abs(x - num) < Math.Abs(y - num) ? x : y);
                Result.Add(find);
                return find;
            }
        }
        public static class RandomExtensions
        {
            public static double NextDouble(
                this Random random,
                double minValue,
                double maxValue)
            {
                return random.NextDouble() * (maxValue - minValue) + minValue;
            }
        }

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, September 25, 2020 5:17 AM
  • Hello Timon,

    Never used i BindingList so i dont know what to expect. Here's a part of my code maybe it will be more easy to understand my goal. What i want is to create a simulation.

    //this part is a moving average i created and totalI allow to create multiple MA starting at different barIndex.
    
    int totalI = 0;
    
    for(int barIndex0 = ChartBars.FromIndex; barIndex0 <= index; barIndex0++)
    	{
    	totalI = barIndex0;
    					
    					
    double closePrice3 = 0;
    double volumes3 = 0;
    double sum4 = 0;
    double sum5 = 0;
    double cma3 = 0;
    				  
    for(int barIndex = totalI; barIndex <= ChartBars.ToIndex; barIndex++)
    		{
    	closePrice3 = Bars.GetClose(barIndex);
    	volumes3 = Bars.GetVolume(barIndex);	
    					
    double clovol3 = closePrice3 * volumes3;	
    					
    					
    sum4 += clovol3++;
    sum5 += volumes3++;
    				
    cma3 = sum4 / sum5;
    					
    				
    		}
    //I cannot create new bars to produce my simulation so i have to add manually new volume using repeat.
    // it will need to be synchronize, i still dont know how i am going to achieve that.
    
    IEnumerable<double> doubles = Enumerable.Repeat(avg, 15);
    
    foreach (Double str in doubles)
                   {
    				   
    lists.Add(nearclose);
    listv.Add(str); 
    var listM = lists.Zip(listv, (first, second) => first * second);
    					
    foreach (var item in listM)
    		{
    sum45 += item;
    						
    						
    		}
    		}	
    				
    //My goal is to create a simulation. My problem is that i cant create more barIndex. 
    
    // the idea is to replace Close.GetValueAt(CurrentBar) by nearclose, nearclose is at the end of the code.				
    				
    double fibo2 = (Close.GetValueAt(CurrentBar) - lowPrice0) / (cma3 - lowPrice0);	
    				
    	
    					
    			 	
    
    
    				
    double sumvolms = 0;
    				
    for(int barIndex = index; barIndex <= ChartBars.ToIndex; barIndex++)
                    {    
    
    double highPrice = Bars.GetHigh(barIndex);
    double lowPrice = Bars.GetLow(barIndex);	
    double vols =  Bars.GetVolume(barIndex); 
    double Price = Bars.GetClose(barIndex);	
    				
    				
    					
    sumvolms += vols; 
    					
    				
    if(cma3 < highPrice && cma3 > lowPrice)
    		{		
    								
    				   
       double newvol =	sumvolms / sumvols;
                            
    							
    
    //some part of the code is missing because its irrelevant.
    //the idea is to send back the value returned in nearclose to replace Close.GetValueAt(CurrentBar) in fibo2.
    //than nearclose will produce a new value but everytime the last value found by nearclose must be stored somewhere in a list or at least nearclose must return every value tested by the if statement.
    
    
    nearclose = ((cmaT - lowPrice0) * df) + lowPrice0;
    
    //right now if i send nearclose to Close.GetValueAt(CurrentBar) it will only return one value. 
    //Once this issue solve nearclose should return a list of values. For example, 10, 11, 10.5, 11.3, 9.8, ...
    //Because cma3	will be moving in the simulation newvol will change and bring a new price to nearclose. We keep store the value, send it to replace Close.GetValueAt(CurrentBar), and the process returned a new nearclose that is stored again to be send back to Close.GetValueAt(CurrentBar). ...			
    }	
    
    }
    }
    }								

    Friday, September 25, 2020 1:21 PM
  • Hi Frank,

    I use BindingList to see the data changes in the Windows Form project. Its usage is basically the same as the normal List.

    There are some variables in the new code. I don’t know their types, so it’s hard for me to fully understand the meaning of this code.

    Where does the code indicate that the collection has changed?

    I feel that the method of finding the closest number only returns one number at a time should be correct.

    We need to call this method every time the collection changes, right?

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, September 29, 2020 6:37 AM
  • Hi Timon,

    The data is coming from a chart and each bar is coming from the barIndex method. The for loop get the bars from some part of the chart delimited by ChartBarsToIndex, index or TotalI. We can extract from each bars close, high, low price with the method Get.Bars.

    nearclose return one value indeed. 

    The first part of the code return the double cma3 which is a moving average. Everytime there is a new bar in the chart, the for loop go fetch the close price and volume of that bar to be calculated to produce the moving average. 

    I want to create a simulation, by using the returned value of nearclose to send it back to the cma. Thats why there is a list.Add(nearclose) and also a listv.Add(str) (this one include new volume). The chart wont let me add new bars so i have to include in my logic the simulation. 

    Now if i returned nearclose right now in the cma it will returned only one value. What i want is everytime i send back the value in list.Add(nearclose)  it produce at the end of the pipe a new nearclose value that will add to the previous one.

    That is why i said once this issue is solved nearclose should return one list of values. For example, 10, 11, 10.5, 11.3, 9.8, ...

    It will predict where the cma is heading with the new data i added. Cause each time a new nearclose will be add in the cma, the cma will draw a futur trend.

    On top of that i have another issue to resolve but first lets find a solution for this one. 

    Thank you

    Tuesday, September 29, 2020 12:34 PM
  • Hi Frank,

    Putting this problem in your complete project is extremely complicated. Can you create a simple project to reproduce this problem so that you can eliminate interference from other factors and focus your energy on this problem?

    By the way, what kind of project is this?

    Windows Forms or WPF or ASP.net?

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, September 30, 2020 5:19 AM
  • Hello Timon,

    Its a model of number prediction. Its a charting software using c#, but i dont know what difference it makes. Its still c#, the proprietary methods are not the culprit. 

    Lets try only with the cma.

    List<double> lists = new List<double>() {closePrice3};
    List<double> listv = new List<double>() {volumes3};
    					
    double closePrice3 = 0;
    double volumes3 = 0;
    double sum4 = 0;
    double sum5 = 0;
    double cma3 = 0;
    				  
    for(int barIndex = ChartBars.FromIndex; barIndex <= ChartBars.ToIndex; barIndex++)
    		{
    	closePrice3 = Bars.GetClose(barIndex);
    	volumes3 = Bars.GetVolume(barIndex);	
    					
    double clovol3 = closePrice3 * volumes3;	
    					
    					
    sum4 += clovol3++;
    sum5 += volumes3++;
    				
    cma3 = sum4 / sum5;
    					
    
    IEnumerable<double> doubles = Enumerable.Repeat(avg, 15);
    
    foreach (Double str in doubles)
                   {
    				   
    lists.Add(nearclose);
    listv.Add(str); 
    var listM = lists.Zip(listv, (first, second) => first * second);
    					
    foreach (var item in listM)
    		{
    sum45 += item;
    						
    						
    		}
    		}	

    We know nearclose return one value for example 3. We want to return the value in lists.Add(nearclose).

    Than we have lists.Add(3) 3 has been added in the list. But nearclose now return 4, but we want to cumulate the values.

    So nearclose should return (3,4, ...) because now 4 will be returned to lists.Add(nearclose) and return a new value 5 (3,4,5...) and it goes on.

    You return each nearclose value in the list to get the next value and cumulate the values returned by nearclose.

    That's the best i can come with for explanation.

    thanks

    Wednesday, September 30, 2020 2:06 PM