Retrieve Key at Index with For Loop - c#

I feel as though I must be missing something very obvious, or C# is simply lacking a feature I've come to expect.
There are typically three for loops in programming.
#1 for (iterator; limit; increment) {}
Increments the iterator after each loop, until it hits the limit.
#2 for (key in object) {}
Assigns key the value of the left-half of the key:value pair at each entry of object.
#3 foreach (value in object) {}
Assigns value the value of the right-half of the key:value pair at each entry of object.
I'm aware that foreach can use a KeyValuePair<TKey,TValue>, but this necessitates assigning a much larger variable the reference to key and value. I don't care about the value, nor do I want to datatype it.
Where is #2 for in for C#?

You can do a foreach (var key in object.keys) (assuming object is a Dictionary) :
Dictionary<object, object> dict = new Dictionary<object, object>();
foreach (var key in dict.Keys)
{
var value = dict[key]; //Not required
}
You could also iterate through Values instead of Keys...but of course it would be impossible to retrieve the corresponding key.

In adition to #MikeH,
if your intention is to iterate over pure object to get Variable Names as Key and its values as values then you can do this with reflection. here is the example
public class Test
{
public string Prop1 {get; set;}
public string Prop2 {get; set;}
public string Prop3 {get; set;}
public string Prop4 {get; set;}
}
public class Program
{
public static void Main()
{
var test = new Test(){
Prop1 = "Test1",
Prop2 = "Test2",
Prop3 = "Test3",
Prop4 = "Test4"
};
foreach (var property in test.GetType().GetProperties())
{
Console.WriteLine("{0} = {1}", property.Name, property.GetValue(test));
}
}
}
besides, If you prefer to use dictionary again you can use
var dict = test.GetType().GetProperties().ToDictionary(x => x.Name, x=> x.GetValue(test));
foreach (var key in dict.Keys)
Console.WriteLine("{0} = {1}", key, dict[key]);

Related

how to get corresponding "Name"

I have a C# dictionary in which I have a corresponding NAME against the ID.
Dictionary<string, List<object>> dict = new Dictionary<string, List<object>>
{
{ "ID", new List<object> { "Id1", "Id2" } },
{ "NAME", new List<object> { "True", "False" } }
};
foreach (var id in dict["ID"])
{
Console.WriteLine(id);
//how to get corresponding "Name". For "Id1" = "True" and for "Id2" = "False"
}
In above code I loop through ID, but how to get corresponding NAME?
I think a better design would be to create a class with the two properties and then iterate. If you find yourself having to sync different data structures for simple data representations then I'd suggest rethinking the design.
public class MyClass
{
public string Id { get; set; }
public bool Name { get; set; }
}
And then hold a List<MyClass> which when you iterate:
foreach (var item in list)
{
// Now access item.Id, item.Name
}
The use of dictionaries is good when you have some sort of natural key for your data and you want to access access an item by that key. As the items are accessed via a hash function accessing by key is done in O(1) whereas searching in a list is O(n). However in your case you are iterating all items in any case so no need for dictionary and arranging the data in a class is a better design.
A bit about the differences and some references:
what is the difference between list<> and dictionary<> in c#
List vs ArrayList vs Dictionary vs Hashtable vs Stack vs Queue?
If you do have control over dictionary data it's best to either use Gilad's answer and store everything in List<MyClass> or to use Dictionary<string, bool> :
Dictionary<string, bool> dict = new Dictionary<string, bool>()
{
{ "Id1", true }, { "Id2", false },
};
But if you do not have control over format of this data and get it as a dictionary from somewhere (for example web service) you could utilize .Zip method to convert this dictionary into one list of either anonymous objects/custom class or Tuples, where Item1 is Id and Item2 is value:
// anonymous object
var data = dict["ID"].Zip(dict["NAME"], (x, y) => new
{
ID = x,
NAME = y
}).ToList();
// tuple
// List<Tuple<object, object>> data = dict["ID"].Zip(dict["NAME"], Tuple.Create).ToList();
foreach (var obj in data)
{
Console.WriteLine(obj.ID + " " obj.NAME);
}
The other answers are probably what you should do to better structure your code. However, if you need to stick to your original use case, you could do something like this:
//Depending on what you're dealing with: Dictionary<string, List<string>>
Dictionary<string, List<object>> dict = new Dictionary<string, List<object>>{
{"ID", new List<object>{"Id1", "Id2"}},
{"NAME", new List<object>{"True", "False"}}
};
foreach(var v in dict.Keys){
Console.WriteLine($"{v} = {string.Join(",", dict[v])}");
}
//Output:
//ID = Id1,Id2
//NAME = True,False
Even if you have the just the mapping of ID and Name you can have very simple variable
Dictionary<string,string> lookup = new Dictionary<string,string>();
lookup.Add("ID1","True")
and if Name is Boolean type then replace string to bool in the
Dictionary<string,bool> lookup = new Dictionary<string,bool>();

Changing object property while storing it in list

lets say i have class with a lot of redundant properties and i want to store them in list, dictionary or whatever
public class Foo
{
public Bar Bar1 {get;set;}
public Bar Bar2 {get;set;}
public Bar Bar3 {get;set;}
public Buzz Buzz1 {get;set;}
public Buzz Buzz2 {get;set;}
public Buzz Buzz3 {get;set;}
public void UpdateObject(Buzz newValue)
{
var dict = new List<KeyValuePair<Bar, Func<Buzz >>>()
{
new KeyValuePair<Bar, Func<Buzz>>(this.Bar1 ,()=>this.Buzz1),
new KeyValuePair<Bar, Func<Buzz>>(this.Bar2 ,() => this.Buzz2 ),
new KeyValuePair<Bar, Func<Buzz>>(this.Bar3 ,() => this.Buzz3 )
};
foreach (var item in dict)
{
if (true)
{
var value = item.Value.Invoke();
value = newValue;
}
}
}
}
of course value is changed but Foo's Buzz1/2/3 property is not. How can i store some kind of reference to object's property in list, get this item and change object's value?
Instead of the key value pairs with a key and a setter, store a key, a getter, and a setter:
List<Tuple<Bar, Func<Buzz>, Action<Buzz>>
Action<Buzz> is a lambda that takes a new value for that Buzz as a parameter.
var dict = new List<Tuple<Bar, Func<Buzz>, Action<Buzz>>
{
new Tuple<Bar, Func<Buzz>, Action<Buzz>(this.Bar1 ,()=>this.Buzz1, x => this.Buzz1 = x),
// ...etc...
};
Not sure why you're doing this, but that'll work.
If it were me, instead of a Tuple or KeyValuePair, I'd write a ThingReference<T> class that takes the two lambdas, and store those in a Dictionary<Bar, ThingReference<Buzz>>.

Get dictionary key object properties

I am trying to retrieve a dictionary's key property, as the key is a class. How do you do it? Here is the class that I use:
public class Item
{
public int Sku { get; set; }
public string Name { get; set; }
public Item()
{
}
}
I am trying to retrieve a property of it for example Name:
Dictionary<Item,double> myDictionary = new Dictionary<Item,double>();
Item item = new Item { Sku = 123, Name = "myItem" };
myDictionary.Add(item,10.5);
So now for example how from this dictionary I would retrieve the item's Name or Sku, or any other property if it would have them?
First, you have to override GetHashCode and Equals if you want to use your class as key of a Dictionary, otherwise you're comparing references.
Here's an example where Equals checks if two items have the same Name.
public class Item
{
public override int GetHashCode()
{
return Name == null ? 0 : Name.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj == null) return false;
if(object.ReferenceEquals(this, obj)) return true;
Item i2 = obj as Item;
if(i2 == null) return false;
return StringComparer.CurrentCulture.Equals(Name, i2.Name);
}
// rest of class ...
}
But the question is not clear. You use a dictionary to lookup elements by the key. So you want to find the value by providing the key. That means you have already a key which makes your question pointless.
However, you can loop a dictionary even if it's not made for this:
foreach(var kv in mydictronary)
{
Item i = kv.Key;
// now you have all properties of it
}
To retrieve your item, you need to use the same item (the same reference). You can do it in such way:
var myDouble = myDictonary[item];
When you use object as a key in a directory, its hash code is use to add/retrieve item from it - you can read more here
If you want use a string to retrieve items, then you should use strings as a key in you dictionary:
Dictonary<string,double> mydictronary = new Dictonary<string,double>();
you can iterate of the dictionary like this:
foreach(var keyValuePair in myDictionary)
{
kvp.Key.
}
then youll get all of the properties
You can use linq:
var item = myDictionary.Where(x => x.Key.Name == "myItem");
var item = myDictionary.Where(x => x.Key.Sku == 123);
You have three options.
You can use the same instance of the class to index, as in var x = myDictionary[item].
You can implementa customer comparer (something that implements IEqualityComparer<Item>), and pass that in to the constructor of your dictionary. For details see MSDN.
You can implement IEquatable<Item> on your Item class. For details see IEquatable on MSDN.
You can access keys from the Dictionary<TKey, TValue>.Keys property.
From MSDN
// To get the keys alone, use the Keys property.
Dictionary<string, string>.KeyCollection keyColl = openWith.Keys;
// The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach( string s in keyColl )
{
Console.WriteLine("Key = {0}", s);
}

Assign .net control property from a dictionary

I'm trying to change a control property from a dictionary so basically the key in the dictionary is the property name of that control and the value will be the property value. is there anyway to do this ?
for example in my dictionary I have "Name" as the key and "buttonSave" as the value, how can I relate them to my control to set its property based on the key and value ?
thanks in advance.
Example for you how to use Reflection in your case with method PropertyInfo.SetValue
public class Customer
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
}
var dictionary = new Dictionary<string, object>
{
{"Id", new Guid()},
{"Name", "Phil"},
{"Phone", "12345678"}
};
var customer = new Customer();
foreach (var pair in dictionary)
{
var propertyInfo = typeof(Customer).GetProperty(pair.Key);
propertyInfo.SetValue(customer, pair.Value, null);
}
using System.Reflection;
look up in MSDN
myControl.GetProperty("Name").SetValue(myControl, "buttonSave", null);
It would also be good idea to check first that the property exists and that it has a setter.
See here for more information on reflection.

How to iterate over this particular type of Dictionary<int, Result>?

I have a bunch of results from the Database that I keep in a Dictionary<int, Result>().
The Result class I have is:
public int Id { get; set; }
public string something { get; set; }
public string somethingtwo { get; set; }
public string somethingthree { get; set; }
public DateTime Posted { get; set; }
public string Location { get; set; }
public bool somethingfour { get; set; }
So, the Dictionary<int, Result> has many Results inside and I'd like to iterate over them. How an I do this? I've tried a few ways, but even I knew they wouldn't work.
I would like to do something like this:
foreach(var result in resultDict)
{
mynewstring = result.Location;
mynewstringtwo = result.Posted;
// etc etc.
}
foreach(var kvp in resultsDict) {
//Do somethign with kvp
UseResult(kvp.Value); //kvp.Value is a Result object
UseKey(kvp.Key); //kvp.Key is the integer key you access it with
}
In the above code kvp is a KeyValuePair<int, Result>. You can access the Key and Value properties to get the integer key of the Dictionary and the Result value associated with that Key. I'll leave it as an excercise/guessing game for you to figure out which property is which! ;-)
As #Wiktor mentions, you can also access the dictionary's Values and Keys collections to do the same thing, but retrieve a sequence of int or Value properties instead.
Alternatives using the other collections:
foreach(var val in resultsDict.Values) {
// The key is not accessible immediately,
// you have to examine the value to figure out the key
UseResult(val); //val is a value.
}
foreach(var key in resultsDict.Keys) {
//The value isn't directly accessible, but you can look it up.
UseResult(resultsDict[key]);
UseKey(key);
}
Dcitionary has a ValueCollection called Values, so the code would be:
foreach (Result r in dict.Values)
{
mynewstring = result.Location;
mynewstringtwo = result.Posted;
}
var dictionary = ...;
foreach ( var result in dictionary.Values )
{
...
}
Is that what you need?
You can use the Values property to iterate over the values of a Dictionary (see also the MSDN page).
Code example:
// Your dictionary
var myResultDictionary = new Dictionary<int, Result>();
foreach (var item in myResultDictionary.Values)
{
// "item" holds a Result object
// Do something with item
}
You can also regularly loop over your Dictionary, however item will be a KeyValuePair (MSDN page) object. You can access the value with the Value property on the variable item.
Code example:
// Your dictionary
var myResultDictionary = new Dictionary<int, Result>();
foreach (var item in myResultDictionary)
{
// "item" holds a KeyValuePair<int, Result> object
// You can access the value (a Result object) by calling "item.Value"
// Do something with item
}
You can iterate over Dictionary.Values, which would be like any other IEnumerable<Result>
Or, you can iterate over Dictionary, which is an IEnumerable<KeyValuePair<int, Result>>
foreach (KeyValuePair<int,Result> item in dictionary)
{
//do stuff
}
foreach(KeyValuePair<int,result> keyValue in yourDictionary)
{
Debug.WriteLine(keyValue.Value);
//or
Debug.WriteLine(keyValue.Key);
}
or the same thing, but using var:
foreach(var keyValue in yourDictionary)
{
Debug.WriteLine(keyValue.Value);
//or
Debug.WriteLine(keyValue.Key);
}
^^ same thing, but var dynamically figures out its own type
or you can do this, if you just need the result:
foreach(var result in yourDictionary.Values)
{
Debug.WriteLine(result);
}
Use a foreach on the Dictionary:
foreach (var keyValue in dictionary)
{
//Use key value here
}

Categories