Best way to set value a List boolean - c#

I'd like to set value in List Boolean.
like this:
List<bool> items = new List<bool> { false, false, false };
for(int i=0; i<items.count; i++)
{
items[i] = true;
}
I tried this, but it doesn't work:
items.ForEach(c=> c = true);
Is there a good way?
Thanks.

To create new array with same values you can use Enumerable.Repeat(TResult, Int32) Method
List<bool> items = new List<bool> { false, false, false };
var allTrue = Enumerable.Repeat(true, items.Count)
To update values of existed instance of List, you must access every item it by index
for (var i = 0; i < items.Count; i++)
{
items[i] = true;
}
if you are using this a lot, wrap loop with an extension method
public static void UpdateAll<T>(this List<T> items, T newValue)
{
for (var i = 0; i < items.Count; i++)
{
items[i] = newValue;
}
}
// Usage
var items = new List<bool> { false, false, false };
items.UpdateAll(true);
But in most of the cases, creating new list with updated values will be most convenient approach.
var items = new List<bool> { false, true, false };
var updated = items.Select(item => true).ToList(); // true, true, true
// Or with some logic
var updated = items.Select(item => !item).ToList(); // true, false, true

You can use the for loop as you mentioned but ForEach loop is not working because iteration variable of a foreach-loop is read-only.

Related

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

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?
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();
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.
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.

How to find out if one element in array has false value for property and if all elements have true value using Linq

I have an array of several objects, they have a isClosed bool property. I would like to know how to determine:
if all values are true
if only one of these values false
using Linq.
You can paraphrase your questions like this:
I would like to know how to determine:
If count of false = 0
If count of false = 1
You can simply use LINQ Count:
switch (collection.Count(x => !x.isClosed))
{
case 0:
// case 1, all values are true
break;
case 1:
// case 2, exactly one of these values is false
break;
default:
// other cases, more than 1 false value
break;
}
With this approach you will iterate through your collection only once.
List<Item> items = new List<Item>()
{
new Item() { IsClosed = true },
new Item() { IsClosed = true },
new Item() { IsClosed = true }
};
var allValuesAreTrue = items.All(it => it.IsClosed);
var onlyOneValueIsTrue = items.Count(it => it.IsClosed) == 1;
Use Linq .all like
It tells you if all the elements in a collection match a certain condition. It is part of the System.Linq namespace in the .NET Framework. It returns true or false.
if (array.All(element => element.isClosed))
{
return true;
}
var count = arr.Count(a => a.isClosed);
if(count == arr.Length)
//all
else if(count == 1)
//only one
else
//not all, but more than one
You can achieve both your desired requirements using the code below :
var list = new List<MyClass>();
var myClass1 = new MyClass {IsClosed = true};
var myClass2 = new MyClass { IsClosed = true };
var myClass3 = new MyClass { IsClosed = true };
list.Add(myClass1);
list.Add(myClass2);
list.Add(myClass3);
var response=list.All(x => x.IsClosed);
It returns true if all elements of your list have the same value.

Comparing a single array against multiple different arays

For a small project on processor affinity, I want to create a simpler method than just a bunch of if(lvProcessors.Items[0].Checked == true && lvProcessors.Items[1] == true etc) comparing their exact values to see which code needs to be transferred to an (IntPtr).
To make the code slightly more efficiƫnt, I would like to compare an array containing booleans, to at least 14 other arrays containing booleans.
Example code:
var CheckState = new[] { lvProcessors.Items[0].Checked, lvProcessors.Items[1].Checked, lvProcessors.Items[2].Checked, lvProcessors.Items[3].Checked };
//setcore1 == 1, setcore2 == 2, etc
var SetCore1 = new[] { true, false,false,false };
var SetCore2 = new[] { true, true, false, false };
var SetCore3 = new[] { false, true, false, false };
var SetCore4 = new[] { true, false, true, false };
var SetCore5 = new[] { false, true, true, false };
var SetCore6 = new[] { true, true, true, false };
var SetCore7 = new[] { false, false, false, true };
var SetCore8 = new[] { true, false, false, true };
var SetCore9 = new[] { false, true, false, true };
var SetCore10 = new[] { true, true, false, true };
var SetCore11 = new[] { false, false, true, true };
var SetCore12 = new[] { true, false, true, true };
var SetCore13 = new[] { false, true, true, true };
var SetCore14 = new[] { true, true, true, true };
int switchcounter = 1;
switch (switchcounter)
{
case 15:
break;
default:
if (Enumerable.SequenceEqual(CheckState,<insertdynamicarrayname))
{
AffinityState = (IntPtr)switchcounter;
}
else
{
switchcounter++;
goto default;
}
break;
}
So if the first checkbox in the listview lvProcessors is checked, the var CheckState will generate an array containing { true, false,false,false }
This in turn must be compared to one of the SetCore arrays, and will in this case cause a match with SetCore1.
So what I would like to know is; how can I create a dynamic arrayname, based on the switchcounter on the code, that will fuse "SetCore" and switchcounter.ToString(), thus creating SetCore1, SetCore2, SetCore3, etc.
[EDIT]
As suggested by #Luaan, I've implemented his code to what I would've like it to be:
var SetCore1 = new[] { true, false, false, false};
[..]
var SetCore15 = new[] { true, true, true, true };
var allSets = new [] { SetCore1, SetCore2, SetCore3,SetCore4,SetCore5,SetCore6,SetCore7,SetCore8,SetCore9,SetCore10,SetCore11,SetCore12,SetCore13,SetCore14,SetCore15 };
foreach (var set in allSets)
{
MessageBox.Show(counter.ToString());
if (Enumerable.SequenceEqual(set, CheckState))
{
AffinityState = (IntPtr)counter;
break;
}
else if (Enumerable.SequenceEqual(set, CheckState) == false)
{
counter++;
}
}
EditProcess.ProcessorAffinity = (IntPtr)AffinityState;
In this code, depending on the input of the listviewcheckboxes, it will match the depending result to a SetCore and using the counter it will give the proper int which is converted at the end of the foreach loop and set the very specific cores(i.e. 1, 2 or 0, 2, 3, etc) to be used for the selected process which has been selected earlier in the code(not visible).
Thanks for the suggestion on bitmasks, they look useful, but currently I have no idea how to implement them without taking half my application apart.
Just make an array of arrays:
var allSets = new [][] { SetCore1, SetCore2, SetCore3, ... }
Then you can use a simple for cycle:
for (var i = 0; i < allSets.Length; i++)
HandleSet(allSets[i]);
Using Enumerable.SequenceEqual is going to be a bit slow. If you care about performance (I don't think you necessarily do in a case like this), have a look at BitArray - it's much smaller in memory, and the match is mostly a simple bitmasking.
EDIT:
If you want to convert between a bool[] and int (or byte, whatever you need), you can use something like this:
public bool[] ToBoolArray(int val)
{
var bits = new bool[sizeof(int) * 8];
for (var i = 0; i < bits.Length; i++)
{
bits[i] = (val & (1 << i)) > 0;
}
return bits;
}
public int ToInt32(bool[] bits)
{
var output = default(int);
for (var i = 0; i < bits.Length; i++)
{
output |= bits[i] ? 1 << i : 0;
}
return output;
}
This avoids having to deal with tons of annoying strings. Using a BitArray this is even simpler - creating a BitArray from int is trivial (there's a constructor), and changing it back to int can be done easily as above, just use bits.Get(i) instead of bits[i].
Or even better, make your own class for handling this:
public sealed class CpuMask
{
private int _bits;
public bool this[int index]
{
get { return (_bits & (1 << index)) > 0; }
set { if (value) _bits |= (1 << index); else _bits &= ~(1 << index); }
}
public CpuMask(int mask)
{
_bits = mask;
}
public CpuMask(IntPtr mask) : this(mask.ToInt32()) { }
public IntPtr ToIntPtr() { return new IntPtr(_bits); }
}

checking two lists contains same property values

I have two lists as follow
var topicsA = new List<Topic>()
{
new Topic(){ TopicCode = "T01", TopicAccessed = false },
new Topic(){ TopicCode = "T02", TopicAccessed = false },
new Topic(){ TopicCode = "T03", TopicAccessed = false }
};
var topicsB = new List<Topic>()
{
new Topic(){ TopicCode = "T01"},
new Topic(){ TopicCode = "T02"}
};
What is a quick way of setting the TopicAccessed value of topicsA to true where the property values of TopicCode are the same in topicsB
for example, in this case T01and T02 would have TopicAccessed set to true
Regards
All answers show quadratic algorithm complexity (Big O). This code snippet shows linear big O:
var accessedTopicsByCode = topicsB.ToDictionary(x => x.TopicCode);
foreach (var t in topicsA)
{
if (accessedTopicsByCode.ContainsKey(t.TopicCode))
{
t.TopicAccessed = true;
}
}
Use a dictionary to have better performance:
var hash = new Dictionary<string,bool>();
foreach(var topicB in topicsB)
{
hash[topicB.TopicCode] = true;
}
foreach(var topicA in topicsA)
{
topicA.TopicAccessed = hash.ContainsKey(topicA.TopicCode);
}
The complexity of this solution is O(n+m) whereas nested loop is O(n*m). ContainsKey's complexity is O(1)
Or you can also use a HashSet because we only need the key, not the value:
var hash = new HashSet<string>();
foreach(var topicB in topicsB)
{
hash.Add(topicB.TopicCode);
}
foreach(var topicA in topicsA)
{
topicA.TopicAccessed = hash.Contains(topicA.TopicCode);
}
This has the same complexity as using a Dictionary, but it's more efficient in memory usage. Contains' complexity is O(1)
You could try something like this:
// We iterate though the items of topicsA list.
foreach(var topicA in topicsA)
{
// If topicsB list contains any item with the same TopicCode like
// the current's item TopicCode, update the TopicAccessed.
if(topicsB.Any(x=>x.TopicCode == topicaA.TopicCode))
{
topicA.TopicAccessed = true;
}
}

how to know which boolean is true

According to this thread Elegantly determine if more than one boolean is "true"
using this part of code...
public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
{
int trueCnt = 0;
foreach(bool b in bools)
if (b && (++trueCnt > threshold))
***//here i need to know which of b is the true***
return true;
return false;
}
I want to know which of bools variable is true?
If you want to know the indices of the true values, use the overload of Select that includes an index parameter:
IList<int> indices = bools.Select((b, i) => new {Index = i, IsTrue = b})
.Where(x => x.IsTrue)
.Select(x => x.Index)
.ToList();
Given a list of bool, this will return a list of the indexes that are true:
var myList = new List<bool>{false, false, true, true, false};
// Will return an IEnumerable containing {2, 3}:
var trueStuff = myList.Select((value, pos) => pos).Where(pos => myList[pos]);
Update: As pointed out in the comment below, the above would only work for a List, and not for an IEnumerable. I'll still leave it here though, as it may be useful in another similar situation.
Also, just for the record, here's a solution (albeit a slightly less elegant one) that should work in either case:
// Note: IEnumerable this time:
IEnumerable<bool> myList = new List<bool> { false, false, true, true, false };
var trueStuff = new List<int>();
int pos = 0;
foreach (var b in myList)
{
if(b){ trueStuff.Add(pos); }
pos++;
}
I want to know which of bools variable is true?
this one uses LINQ
IList<bool> _result = bools.Where(x => x == true);
I'm not sure if I am understanding this correctly, but if you wanted to know which Boolean values in an enumerated list are true and which ones are false, you could modify that routine to be something like this:
public static string GetBoolString(IEnumerable<bool> bools)
{
var boolArray = bools.ToArray();
char[] data = new char[boolArray.Length];
for (int i = 0; i < boolArray.Length; i++)
{
data[i] = boolArray[i] ? '1' : '0';
}
return new string(data);
}
Note that I am not presenting any "elegant" solution; just getting it done.
var firsttrue = bools.First(b => b);
If you switch from IEnumerable to something with an inbuilt index (like an array or List), you can do this, to return a list of the indices that are true:
public IEnumerable<int> GetTrueIndices(bool[] b)
{
return Enumerable.Range(0, b.Length).Where(i => b[i]);
}
with a list it would be this:
public IEnumerable<int> GetTrueIndices(List<bool> b)
{
return Enumerable.Range(0, b.Count).Where(i => b[i]);
}
Don't use IEnumerable if you want to work with indices, but use arrays.
To get indices use for loop and iterate over the array.

Categories