Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Infecting\transmitting value to the adjacent items of list, in C#

Tags:

c#

list

linq

There is a list of binary values:

List<bool> myList = new List<bool>(){true, true, false, false, true, false, false, false, true, true, true, false, false};

my algorithm aims to convert any false item to true, if they are adjacent to a true value:

result = {true, true, true, true, true, true, false, true, true, true, true, true, false}

My solution works, as you will see. I can do it through two different loops, and then zip two lists:

List<bool> firstList = new List<bool>();
List<bool> secondList = new List<bool>();
for(int i=0; i<myList.Count()-1; i++){
  if(myList[i]==true){
    firstList[i]=true;
    firstList[i+1]=true;
  }
}

for(int i=1; i<myList.Count(); i++){
  if(myList[i]==true){
    secondList[i]=true;
    secondList[i-1]=true;
  }
}

List<bool> finalList = firstList.Zip(secondList, (a,b)=>a||b).ToList();

However, it doesn't seem to be the best solution since the problem looks very easy. Any idea to do it through one loop or preferably using linq?

like image 720
Aryan Firouzian Avatar asked Dec 14 '17 15:12

Aryan Firouzian


3 Answers

Here is a Linq approach

Basically it has the same behaviour as your approach - the element self x, the previous .ElementAtOrDefault(i - 1) or the next .ElementAtOrDefault(i + 1) element has to be true.

List<bool> result = myList.Select((x, i) => x || myList.ElementAtOrDefault(i - 1) || myList.ElementAtOrDefault(i + 1)).ToList();
like image 184
fubo Avatar answered Nov 10 '22 12:11

fubo


You can do it in one loop:

List<bool> result = myList.Select((b, index) => 
                  b || 
                  (index > 0 && myList[index-1]) || 
                  (index < (myList.Count - 1) && myList[index+1])).ToList();

This takes every b in your myList and checks (via index) if this itself or the adjacting values are true. Of course we have to check index for the list boundaries.

like image 6
René Vogt Avatar answered Nov 10 '22 12:11

René Vogt


I don't think this is particularly readable, but:

var indexesToChange = 
    Enumerable.Range(0, myList.Count)
    .Where(n => myList[n]
        || (n-1 >= 0 && myList[n-1])
        || (n+1 < myList.Count && myList[n+1]))
    .ToList();

foreach (var i in indexesToChange)
{
    myList[i] = true;
}

This will update the old list. You could copy to a new list in the foreach loop if you don't want to change the old one.

like image 1
JamesFaix Avatar answered Nov 10 '22 13:11

JamesFaix