How to change all values in a Dictionary<string, bool>? - c#

So I have a Dictionary<string, bool> and all I want to do is iterate over it and set all values to false in the dictionary. What is the easiest way to do that?
I tried this:
foreach (string key in parameterDictionary.Keys)
parameterDictionary[key] = false;
However I get the error: "Collection was modified; enumeration operation may not execute."
Is there a better way to do this?

Just change the enumeration source to something other than the dictionary.
foreach (string key in parameterDictionary.Keys.ToList())
parameterDictionary[key] = false;
For .net 2.0
foreach (string key in new List<TKey>(parameterDictionary.Keys))
parameterDictionary[key] = false;

In .net 5 the following snippet no longer throws:
var d = new Dictionary<string, int> { { "a", 0 }, { "b", 0 }, { "c", 0 }};
foreach (var k in d.Keys){
d[k] = 1;
}

Related

Iterate through IList<Hashtable> by index in ASP.NET MVC

I am having some trouble iterating through a IList<Hashtable>. I am trying to iterate it by index i.e.:
I have an IList<Hashtable> with 3 different Hashtables in it. I want to foreach each one by IList's index. In example:
I want first to foreach all KeyValuePairs in Hashtable in IList index=0. When finished do some stuff and then foreach all KeyValuePairs in Hashtable in IList index=1 and so on until all Hashtables are iterated through. Currently the code is as follows:
variable data is an IList<Hashtable> with 3 Hashtables in it.
foreach (Hashtable rowData in data[index])
{
some code here...
}
I get the following error:
Unable to cast object of type 'System.Collections.DictionaryEntry' to type 'System.Collections.Hashtable'.
If you want to iterate through an IList<HashTable> via the indexer operator:
IList<Hashtable> data = new List<Hashtable>
{
new Hashtable { { "a", "b"} },
new Hashtable { { "c", "d"}, {"e", "f"} },
new Hashtable { { "g", "h"} },
};
Then you can do the following:
//Iterate through the IList but interested only about the index
foreach (var index in data.Select((_, idx) => idx))
{
//Iterate through the Hashtable which contains DictionaryEntry elements
foreach (DictionaryEntry rowData in data[index])
{
Console.WriteLine($"{rowData.Key} = {rowData.Value}");
}
}
Reference for the Hashtable contains DictionaryEntry items.
The output will be either this:
a = b
c = d
e = f
g = h
or that:
a = b
e = f
c = d
g = h
Try this code
foreach(Hashtable rowData in data)
{
foreach(DictionaryEntry pair in rowData)
{
Console.WriteLine($"{pair.Key} {pair.Value}");
}
}

Foreach in Foreach iterate at the same

I would like to know how to add item to the dictionary from the first foreach loop and the second foreach loop at the same time..
For example - the first loop adds the first contents to the item and starts the second loop which I want it to add the first item in the loop and then starts the outside loop without reading the second item. Do the same and add the second item from the second loop.
Sorry if the question is confusing..Weak english.
List<object> items = new List<object>();
DeviceSettings deviceSettings = new DeviceSettings();
List<object> deviceName = deviceSettings.GetMonitorFriendlyName();
using (ManagementObjectCollection moc = searcher.Get())
{
foreach (ManagementObject mo in moc)
{
Dictionary<string, object> item = new Dictionary<string, object>();
ConnectedMonitor_Number = searcher.Get().Count;
item.Add("DefaultMonitorLength", DefaultMonitor_Width);
item.Add("DefaultMonitorHeight", DefaultMonitor_Height);
item.Add("ConnectedMonitor_Numb", Convert.ToString(ConnectedMonitor_Number));
item.Add("Caption", Convert.ToString(mo["Caption"]));
item.Add("Name", Convert.ToString(mo["Name"]));
item.Add("Description", Convert.ToString(mo["Description"]));
item.Add("DeviceID", Convert.ToString(mo["DeviceID"]));
item.Add("Manufacturer", Convert.ToString(mo["Manufacturer"]));
string[] HardwareID = (string[])mo["HardwareID"];
item.Add("HardwareID", string.Join(";", HardwareID));
item.Add("Status", Convert.ToString(mo["Status"]));
foreach (Dictionary<string, string> dm in deviceName)
{
item["monitorname"] = Convert.ToString(dm["monitorname"]);
}
items.Add(item);
}
}
---This is the devicesettings.cs ---
public static string MonitorFriendlyName(LUID adapterId, uint targetId)
{
DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME();
deviceName.header.size = (uint)Marshal.SizeOf(typeof(DISPLAYCONFIG_TARGET_DEVICE_NAME));
deviceName.header.adapterId = adapterId;
deviceName.header.id = targetId;
deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
int error = DisplayConfigGetDeviceInfo(ref deviceName);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
return deviceName.monitorFriendlyDeviceName;
}
public List<object> GetMonitorFriendlyName()
{
try
{
List<object> items = new List<object>();
uint PathCount, ModeCount;
int error = GetDisplayConfigBufferSizes(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
out PathCount, out ModeCount);
if (error != ERROR_SUCCESS)
{
throw new Win32Exception(error);
}
DISPLAYCONFIG_PATH_INFO[] DisplayPaths = new DISPLAYCONFIG_PATH_INFO[PathCount];
DISPLAYCONFIG_MODE_INFO[] DisplayModes = new DISPLAYCONFIG_MODE_INFO[ModeCount];
error = QueryDisplayConfig(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
ref PathCount, DisplayPaths, ref ModeCount, DisplayModes, IntPtr.Zero);
for (int i = 1; i < ModeCount; i++)
{
if (DisplayModes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
{
Dictionary<string, string> item = new Dictionary<string, string>();
item["MonitorName"] = (MonitorFriendlyName(DisplayModes[i].adapterId, DisplayModes[i].id));
items.Add(item);
}
}
return items;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
You appear to be overwriting your monitorname key in your dictionary entry every time you iterate. This would set every single item to have the same monitor name. Try something like this:
List<object> items = new List<object>();
DeviceSettings deviceSettings = new DeviceSettings();
List<object> deviceNames = deviceSettings.GetMonitorFriendlyName();
using (ManagementObjectCollection moc = searcher.Get())
{
var managementObjects = moc.Cast<ManagementObject>().ToArray();
ConnectedMonitor_Number = managementObjects.Length;
for (int i = 0; i < managementObjects.Length; i++)
{
object device = deviceNames[i];
ManagementObject mo = managementObjects[i];
Dictionary<string, object> item = new Dictionary<string, object>
{
{ "DefaultMonitorLength", DefaultMonitor_Width },
{ "DefaultMonitorHeight", DefaultMonitor_Height },
{ "ConnectedMonitor_Numb", Convert.ToString(ConnectedMonitor_Number) },
{ "Caption", Convert.ToString(mo["Caption"]) },
{ "Name", Convert.ToString(mo["Name"]) },
{ "Description", Convert.ToString(mo["Description"]) },
{ "DeviceID", Convert.ToString(mo["DeviceID"]) },
{ "Manufacturer", Convert.ToString(mo["Manufacturer"]) },
{ "HardwareID", string.Join(";", (string[])mo["HardwareID"]) },
{ "Status", Convert.ToString(mo["Status"]) },
{ "monitorname", Convert.ToString(device["monitorname"])}
};
items.Add(item);
}
}
Note this doesn't compile because you are declaring deviceNames as a List<object> however appear to treat it like a Dictionary<string,string>. Is there a cast we're not seeing? Also this answer is predicated on the assumption you're searching only for connected monitors.
Update:
Seeing where you copied your source from, you need to revert your code back to what the original author was doing. If you really want a dictionary, you'll need to pick a key that you can tie into your WMI search results from above.
If I got your question this may be logic you looking for(Not sure). Use an outer loop to just hold item and an inner loop to do a real operation.
foreach (ManagementObject mo in moc)
{
foreach (item-no-n mo in ManagementObject )
{
///1st item loop to n-item
}
foreach (item-no-n mo in ManagementObject )
{
///1st item loop to n-item
}
}
Edit after looking at the updated code.
Your code seems to be all messed up and I am sure it is not even executing completely.
You are using same Key for dictionary (Dictionary<string, string> item) in your list of Dictionaries (List<object> items). This means, at any given time, you have exactly one value in your dictionary. What are you trying to achieve by this?
Now, coming to your question where you are trying to loop through the second foreach just once and exit.
I am seeing a major issue here. You are trying to access value of the key "monitorname" whereas, at the source, you are assigning the value to key "MonitorName".
Based on your Dictionary initialisation, keys in your Dictionary are case-sensitive, and here you are trying to access wrong key.
Since you always have a single entry in the dictionary with key "MonitorName", this line of code will throw KeyNotFoundException at runtime.
But you have reported that adding break; to the second foreach breaks the first foreach. My guess is that you have not even debugged the code and have posted your question on assumption based on the output you are getting. Which is caused due to runtime exception and not because the break; is not working as expected.
Although there are many things unclear in your code, I am assuming you have a valid reason to have them that way.
The below code should fix your problem:
foreach (Dictionary<string, string> dm in deviceName)
{
item["monitorname"] = Convert.ToString(dm["MonitorName"]);
break;
}
Notice dm["MonitorName"] where I have updated the key from "monitorname" to "MonitorName".
Also remember to use correct key while accessing item["monitorname"]
Hope this helps!

Prevent collection modified exception in a foreach loop in c#

I'm iterating over a dictionary Dictionary<double, int> diametersAndQuantities and the dictionary is modified. Obviously I'm getting an exception that the collection has been modified. How can I prevent this from happening?
foreach (var diametersAndQuantity in diametersAndQuantities)
{
// some operations here
// update
diametersAndQuantities[db] = n;
}
You can create a temporary list of the KeyValuePairs to iterate over and still update the dictionary.
foreach (var diametersAndQuantity in diametersAndQuantities.ToList())
{
// some operations here
// update
diametersAndQuantities[diametersAndQuantity.Key] = n;
}
you can use the ToList() to get the enumeration to be evaluated
similar to accepted answer - maybe a little faster
should use less memory
Dictionary<int, int> dic = new Dictionary<int, int>() { { 1, 2 }, { 2, 3 }, { 3, 2 } };
foreach (int value in dic.Values)
Debug.WriteLine(value);
foreach (int key in dic.Keys.ToList())
dic[key] = 12;
foreach (int value in dic.Values)
Debug.WriteLine(value);
Debug.WriteLine("done");

How to remove strings in list from another list?

I have 2 list which names are listA and listB.
I want to remove strings in listB which are in listA, but I want to do this in this way:
if listA contains: "bar", "bar", "bar", "foo"
and listB contains : "bar"
it removes only 1 bar and the result will be:
"bar", "bar", "foo"
the code I wrote removes all "bar":
List<string> result = listA.Except(listB).ToList();
You can try to remove it one by one:
foreach (var word in listB)
listA.Remove(word);
The Remove method will only remove one element at a time and is not throwing exception (but returning false) when the item is not found: https://msdn.microsoft.com/en-us/library/cd666k3e(v=vs.110).aspx
var listA = new List<string>() { "bar", "bar", "bar", "foo" };
var listB = new List<string>() { "bar" };
foreach (var word in listB){
listA.Remove(word);
}
Here is a more efficient way to do that:
var countB = new Dictionary<string, int>(listB.Count);
foreach (var x in listB)
{
int count;
countB.TryGetValue(x, out count);
countB[x] = count + 1;
}
listA.RemoveAll(x =>
{
int count;
if (!countB.TryGetValue(x, out count)) return false;
if (count == 1)
countB.Remove(x);
else
countB[x] = count - 1;
return true;
});
This is a faster method but it is likely to change the order of elements of first list. Steps:
Map the listA to a Dictionary<string, int> (let's call it listAMap), where key is the element of the list and value is the total number of times that value has occurred in listA;
Iterate through listB and for every element of listB, if that element is in the listAMap, reduce its count;
Get the keys of listMapA using Keys property of C# dictionaries, and iterate through all the keys. For every key which has positive value, add that key to another list a total of its count times. So if an entry is "bar" -> 2, then add "bar" twice in the new list.
Total run time of the algorithm is O(m + n), where m and n are number of elements in both the original lists. It is a better running time than other approaches mentioned here which have O(m * n) running time. Obviously this algorithm uses more space.
Supportive Code for the algorithm above:
//Step-1: Create the dictionary...
var listAMap = new Dictionary<string, int>();
foreach (var listAElement in listA)
{
listAMap.ContainsKey(listAElement) ? listAMap[listAElement]++ : listAMap.Add(listAElement, 1);
}
// Step-2: Remove the listB elements from dictionary...
foreach (var listBElement in listB)
{
if (listAMap.Contains(listBElement)) listAMap[listBElement]--;
}
//Step-3: Create the new list from pruned dictionary...
var prunedListA = new List<string>();
foreach (var key in listAMap.Keys)
{
if (listAMap[key] <= 0) continue;
for (var count = 0; count < listAMap[key]; count++)
{
prunedListA.Add(key);
}
}
//prunedListA contains the desired elements now.

foreach items in hashtable

I need to use Hastable (Not List and not Dictionary), and I have many variables with keys. I add keys and variables to class, and use it in my program. But I don't know how to parse Hashtable. I tried this:
Hashtable toboofer = null;
string path = #"my.bin";
FileStream fin = File.OpenRead(path);
try
{
BinaryFormatter bf = new BinaryFormatter();
toboofer = (Hashtable)bf.Deserialize(fin);
for (int i = 0; i <= toboofer.Count; i++ )
//foreach (KeyValuePair<string, string> kvp in toboofer)
{
myclass cl = new myclass();
cl.Fio = toboofer[i].ToString();
cl.About = toboofer[i].ToString();
}
}
but I have an error. When I try string item or cycle for I have an error too.
Hashtable has DictionaryEntry as collection element
foreach (DictionaryEntry entry in toboofer)
{
// do something
}
Make list of myclass from hashtable:
var listOfMyClass = toboofer.Cast<DictionaryEntry>().
Select(e => new myclass()
{ Fio = e.Key.ToString(), About = e.Value.ToString() });
try this hashtable make use if DictionaryEntry, where KeyValuePair generic used by generic dictionary .Net 2 (and onwards)
Aslo note that Hashtable doesnt have generic version of it and Each element in hastable represented by DictionaryEntry
foreach (DictionaryEntry entry in hashtable)
{
Console.WriteLine("{0}, {1}", entry.Key, entry.Value);
}

Categories