Comparing a single array against multiple different arays - c#

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); }
}

Related

Best way to set value a List boolean

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.

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.

Determine if all elements of a List are true or false [duplicate]

This question already has answers here:
Check if all items are the same in a List
(5 answers)
Closed 7 years ago.
i have to chek if all elements of a List<bool> are true or all elements are false
List<bool> b1 = new List<bool>() { true, true, true, true }; //valid
List<bool> b2 = new List<bool>() { false, false, false, false }; //valid
List<bool> b3 = new List<bool>() { true, false, false, true }; //not valid
Is there a Linq approach instead of my current loop?
bool isValid = true;
for (int i = 1; i < b3.Count; i++)
{
if (b3[i] != b3[i - 1])
isValid = false;
}
bool result = myList.All(a => a) || myList.All(a => !a);
This should work

Refactoring code with the Extract method

In my application, we have a class which generates information within a database as static centralised data. This class is called 'GenerateOwner'. Within this class we are creating multiple entries of type 'FieldValidation'.
FieldValidation swedishFieldValidation1 = new FieldValidation
{
IsRequired = false,
DataType = "String",
Length = 0,
Min = 0,
Max = 255,
FieldValidationType = _bancPaydatabase.FieldValidationTypes.FirstOrDefault(o => o.FieldName == "InvoiceNumber"),
IsVisible = true,
Owner_Country = swedishOwnerCountry
};
FieldValidation swedishFieldValidation2 = new FieldValidation
{
IsRequired = false,
DataType = "String",
Length = 0,
Min = 0,
Max = 255,
FieldValidationType = _bancPaydatabase.FieldValidationTypes.FirstOrDefault(o => o.FieldName == "InvoiceTypeId"),
IsVisible = true,
Owner_Country = swedishOwnerCountry
};
And so on. There are about 20 or so entries all very much similar. My question is, how would I best refactor this code to prevent duplicating the same entries over and over? I have been pointed towards the Extract method, but I am unsure of how to implement this in my code. Thanks in advance.
Extract method is a refactoring method that extracts code into its own method. If the extracted part needs parameters they are passed as parameters to the method.
In your code the code is exactly the same except for the field name; The field name would be a parameter to your method.
The result would look like this:
private FieldValidation CreateFieldValidation(string fieldName)
{
return new FieldValidation
{
IsRequired = false,
DataType = "String",
Length = 0,
Min = 0,
Max = 255,
FieldValidationType =
_bancPaydatabase.FieldValidationTypes
.FirstOrDefault(o => o.FieldName == fieldName),
IsVisible = true,
Owner_Country = swedishOwnerCountry
};
}
Usage would be now like this:
FieldValidation swedishFieldValidation1 = CreateFieldValidation("InvoiceNumber");
FieldValidation swedishFieldValidation2 = CreateFieldValidation("InvoiceTypeId");
If owner country would need to change, too, you would also make it a parameter in the method.

Categories