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}");
}
}
Related
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");
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.
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);
}
This is my code:
List<string> l1 = new List<string> { "a", "b", "c" };
List<string> l2 = new List<string> { "x", "y", "z" };
foreach (var item in l1)
{
item = MyFunction(item);
}
foreach (var item in l1)
{
item = MyFunction(item);
}
Is there a way to iterate both the Lists in a single foreach statement ?
Assuming the type of the List objects are the same you can use Concat.
foreach (var item in l1.Concat(l2))
{
item = MyFunction(item);
}
You could use the Concat() function:
foreach(var item in l1.Concat(l2))
item = MyFunction(item);
Be aware that reassigning the counter variable of an Enumerable-based loop can cause exceptions relating to changing the underlying IEnumerable.
Maybe something like this:
var mergedList = 11.Union(l2).ToList();
foreach (var item in mergedList)
{
item = MyFunction(item);
}
The Union removes any duplicates. The Concat() method does not. So Union might be preferrable. It depends on the composition of the lists.
I have two List<T> objects:
For example:
List 1:
ID, Value where Id is populated and value is blank and it contains say IDs from 1 to 10.
1,""
2,""
...
10,""
List 2:
ID, Value and other attributes all filled with values but this list is a subset of List 1 in terms of IDs. (e.g only 3 items)
2,67
4,90
5,98
What I want is a merged list 1, but with updated values. Does anyone have any good extension method which will do this or any elegent code to perform this operation. The final list should be:
ID, Value
1,""
2,67 //value from list 2
3,""
4,90
5,98
6,""
...
10,""
use linq: list1=list2.Union(list1);
I would probably use a dictionary rather than a list:
// sample data
var original = new Dictionary<int, int?>();
for (int i = 1; i <= 10; i++)
{
original.Add(i, null);
}
var updated = new Dictionary<int, int>();
updated.Add(2, 67);
updated.Add(4, 90);
updated.Add(5, 98);
updated.Add(11, 20); // add
// merge
foreach (var pair in updated)
{
original[pair.Key] = pair.Value;
}
// show results
foreach (var pair in original.OrderBy(x => x.Key))
{
Console.WriteLine(pair.Key + ": " + pair.Value);
}
If you are talking about properties of an object, it will be trickier, but still doable.
This is O(m*n) but should do the job for arbitrary lists
foreach (var record in List1)
{
var other = List2.FirstOrDefault(x => x.Key == record.Key);
if(other != null) record.Value = other.Value;
}
If the lists are guaranteed ordered, then it could be brought down to O(n) at the cost of more code. The algortihm would be
Current items start as head of each list
While items remain in both lists
If the current item of list1 has lower key than list2 advance to next in list1
else if the current item of list2 has lower key than list1 advance to next in list2
else copy value from current list2 item into list1 item and advance both lists.
If you have both lists sorted by ID, you can use a variation of the classical merge algorithm:
int pos = 0;
foreach (var e in list2) {
pos = list1.FindIndex(pos, x => x.Id==e.Id);
list1[pos].Value = e.Value;
}
Note that this also requires list2 to be a strict subset of list1 in terms of ID (i.e. list1 really contains all ids of list2)
Of course you can also wrap this in an extension method
public static void UpdateWith<T>(this List<T> list1, List<T> list2)
where T:SomeIdValueSupertype {
int pos = 0;
foreach (var e in list2) {
pos = list1.FindIndex(pos, x => x.Id==e.Id);
list1[pos].Value = e.Value;
}
}
private void btnSearch_Click(object sender, EventArgs e)
{
String searchBy = cmbSearchBy.Text.ToString();
String searchFor = txtSearchFor.Text.Trim();
var List3 = (from row in JobTitleDB.jobList
where (row.JID.ToString()+row.JobTitleName.ToString().ToLower()).Contains(searchFor.ToLower())
select row).ToList();
if (searchBy == "All")
{
dgJobTitles.DataSource = null;
//dgJobTitles.DataSource = List1;
//dgJobTitles.DataSource = List2;
//dgJobTitles.DataSource = List1.Concat(List2);
//dgJobTitles.DataSource = List1.Union(List2);
dgJobTitles.DataSource = List3;
//dgJobTitles.DataSource=List1.AddRange(List2);
}
}
Dictionary<int, string> List1 = new Dictionary<int, string>();
List1.Add(1,"");
List1.Add(2,"");
List1.Add(3,"");
List1.Add(4,"");
List1.Add(5,"");
List1.Add(6,"");
Dictionary<int, string> List2 = new Dictionary<int, string>();
List2.Add(2, "two");
List2.Add(4, "four");
List2.Add(6, "six");
var Result = List1.Select(x => new KeyValuePair<int, string>(x.Key, List2.ContainsKey(x.Key) ? List2[x.Key] : x.Value)).ToList();