0

I have 2 lists: list and listLookup

How do I update all the ValueToGet in list with closes KeyLookup in listLookup?

https://dotnetfiddle.net/QHd0Rr

    using System.Collections.Generic;
    
    public class Program
    {
        public static void Main()
        {
            //Arrange
            //Keys needed to get ValueToGet property
            var key1 = new WidgetA{Id = 1, Key = 52};
            var key2 = new WidgetA{Id = 2, Key = 102};
            var key3 = new WidgetA{Id = 3, Key = 152};
            List<WidgetA> list = new List<WidgetA>();
            list.Add(key1);
            list.Add(key2);
            list.Add(key3);
            //Lookups
            var keyLookup1 = new WidgetB()
            {Id = 1, KeyLookup = 50, ValueLookup = "Fifty"};
            var keyLookup2 = new WidgetB()
            {Id = 2, KeyLookup = 100, ValueLookup = "One hundred"};
            var keyLookup3 = new WidgetB()
            {Id = 3, KeyLookup = 150, ValueLookup = "One hundred and fifty"};
            List<WidgetB> listLookup = new List<WidgetB>();
            listLookup.Add(keyLookup1);
            listLookup.Add(keyLookup2);
            listLookup.Add(keyLookup3);
        //Act
        /* Update all rows for ValueToGet property in list, using the closes KeyLookup in listLookup 

    Expected result:  
        
    key1: Key = 52, ValueToGet = "Fifty"
    key2: Key = 102, ValueToGet = “One hundred”
    key3: Key = 152, ValueToGet = “One hundred and fifty”       
            */
        }
    }

public class WidgetA
{
    public int Id { get; set; }

    public int Key { get; set; }

    public string ValueToGet { get; set; }
}

public class WidgetB
{
    public int Id { get; set; }

    public int KeyLookup { get; set; }

    public string ValueLookup { get; set; }
}

In SQL it would be kind of like this but finding the closest key somehow:

update list
set ValueToGet = ValueLookup
from list l1
join listLookup l2
on l1.key = l2.keyLookup
Rod
  • 14,529
  • 31
  • 118
  • 230

1 Answers1

0

If we define closest as:

  • Take the KeyLookup that is lower than the current Key
  • If there is no KeyLookup lower than the current key, take the closest higher one

Than this would solve your problem

private static void AddValueLookup(IEnumerable<WidgetA> list, IEnumerable<WidgetB> listLookup)
{
    // Ensure the collection is ordered
    using var bENumerator = listLookup.OrderBy(b => b.KeyLookup).GetEnumerator();
    
    // Get the first two values.
    // If the collection does not have at least one value, return.
    if(!bENumerator.MoveNext())
        return;
    var currentKey = bENumerator.Current;
    
    bENumerator.MoveNext();
    var nextKey = bENumerator.Current;
    
    // Ensure the collection is ordered.
    // If the list contains a key that is smaller, than the smallest one in the lookup list, 
    // it will get the next higher ValueLookup
    foreach (var a in list.OrderBy(a => a.Key))
    {
        while (a.Key > nextKey.KeyLookup)
        {
            currentKey = nextKey;
            if (bENumerator.MoveNext())
                nextKey = bENumerator.Current;
            else
                break;
        }
        a.ValueLookup = currentKey.ValueLookup;
    }
}
wertzui
  • 5,148
  • 3
  • 31
  • 51