Using LINQ to parse XML into Dictionary - c#

I have a configuration file such as:
<ConfigurationFile>
<Config name="some.configuration.setting" value="some.configuration.value"/>
<Config name="some.configuration.setting2" value="some.configuration.value2"/>
...
</ConfigurationFile>
I am trying to read this to XML and convert it to a Dictionary. I tried coding something liek this but it is obviously wrong as it does not compile.
Dictionary<string, string> configDictionary = (from configDatum in xmlDocument.Descendants("Config")
select new
{
Name = configDatum.Attribute("name").Value,
Value = configDatum.Attribute("value").Value,
}).ToDictionary<string, string>(Something shoudl go here...?);
If someone could tell me how to get this working it would be really helpful. I could always, of course, read it

To give a more detailed answer - you can use ToDictionary exactly as you wrote in your question. In the missing part, you need to specify "key selector" and "value selector" these are two functions that tell the ToDictionary method which part of the object that you're converting is a key and which is a value. You already extracted these two into an anonymous type, so you can write:
var configDictionary =
(from configDatum in xmlDocument.Descendants("Config")
select new {
Name = configDatum.Attribute("name").Value,
Value = configDatum.Attribute("value").Value,
}).ToDictionary(o => o.Name, o => o.Value);
Note that I removed the generic type parameter specification. The C# compiler figures that automatically (and we're using an overload with three generic arguments). However, you can avoid using anonymous type - in the version above, you just create it to temporary store the value. The simplest version would be just:
var configDictionary =
xmlDocument.Descendants("Config").ToDictionary(
datum => datum.Attribute("name").Value,
datum => datum.Attribute("value").Value );

Your call to ToDictionary needs a key and value selector. Starting with that you have, it can be
var dictionary = yourQuery.ToDictionary(item => item.Name, item => item.Value);

It isn't necessary to have the query as you're just doing a projection. Move the projection into the call to ToDictionary():
var configDictionary = xmlDocument.Descendants("Config")
.ToDictionary(e => e.Attribute("name").Value,
e => e.Attribute("value").Value);

Related

Using Lookup in Linq

Need to fetch the first record from Lookup when a condition is satisfied. In below, resId will be key having one or more lists value. In vb, used the below code to fetch the record having resId and record satisfying the below condition. It works perfect.. how can I use the same logic with C#
Lookup<Guid, Class> responseLookup;
result = responseLookup(Guid).FirstOrDefault(
Function(x) catId.Equals(x.catCode)
Tried to convert but was receiving "Method name expected" error
This should work:
responseLookup[Guid].FirstOrDefault(x => catId.Equals(x.catCode))
The => is a lambda-expression. In your case a delegate that excepts a single instance from your list and returns a bool.
Assuming Guid in responseLookup(Guid) is some Guid value, not the type name, the following should work (I suggest using standard naming conventions and refrain from using BCL type names as variable names):
Guid guid = ...;
var result = responseLookup[guid]
.FirstOrDefault(x => catId.Equals(x.catCode));

using lambda, how to apply an existing function to all elements of a list?

Excuse me, a quick question:
I have a list of strings, string are full paths of some files. I would like to get only the filename without the path neither the extension for each string (and to understand lambda more)
Based on the lambda expression in How to bind a List to a DataGridView control? I am trying something like the below:
FilesName = Directory.GetFiles(fbd.SelectedPath).ToList(); // full path
List<string> FilesNameWithoutPath = AllVideosFileNames.ForEach(x => Path.GetFileNameWithoutExtension(x)); // I want only the filename
AllVideosGrid.DataSource = FilesNameWithoutPath.ConvertAll(x => new { Value = x }); // to then bind it with the grid
The error is:
Can not convert void() to List of string
So I want to apply Path.GetFileNameWithoutExtension() for each string in FilesName. And would appreciate any extra description on how Lamba works in this case.
ForEach will execute some code on each item in your list, but will not return anything (see: List<T>.ForEach Method). What you want to do is Select the result of the method (see: Enumerable.Select<TSource, TResult> Method), which would look something like:
List<string> FilesNameWithoutPath = AllVideosFileNames
.Select(x => Path.GetFileNameWithoutExtension(x))
.ToList();
You are using List<T>.ForEach method which takes each element in the list and applies the given function to them, but it doesn't return anything. So what you are doing basically is getting each file name and throwing them away.
What you need is a Select instead of ForEach:
var fileNamesWithoutPath = AllVideosFileNames
.Select(x => Path.GetFileNameWithoutExtension(x))
.ToList();
AllVideosGrid.DataSource = fileNamesWithoutPath;
This will project each item, apply Path.GetFileNameWithoutExtension to them and return the result, then you put that result into a list by ToList.
Note that you can also shorten the Select using a method group without declaring a lambda variable:
.Select(Path.GetFileNameWithoutExtension)

Linq: Except on two different types of dictionaries

i have 2 different types of dictionaries Dictionary<int, Fooclass> oldDic and Dictionary<int, string> barList newDic . Now i need to compare values in both dictionaries. for Example key can be in
oldDic : 1,2,3
newDic : 1,2,3,4
Expected Output : 4
Now i need to compare both dictionaries on basis of their keys
any help would be appreciated.
Edit :
Output should be like second dictionary(newDic) but this will contain some value of 2nd dictionary's(oldDic). For example
1,"fooString" Where fooString is some value in Fooclass's someproperty....
For more clarity see this which doesn't worked for me
var addedList = from list1 in baseListDic
join list2 in trackerlist on list1.Key equals list2.Key
select new { key = list1.Key, value = list1.Value._lead };
here baseListDic is oldDic and trackerlist is newDic....
Let me know if i'm still not clear...
It would be easier to just create a new dictionary based on the new dictionary ignoring items that have the same key in the old dictionary.
var result = newDic
.Where(kvp => !oldDic.ContainsKey(kvp.Key))
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
Note: Despite your question saying "i need to compare values in both dictionaries" (emphasis mine) your example seems to be demonstrating just comparison of keys so I've gone with that. If it is values you need to compare you might want to give an example of what you mean and if they are easily convertible or comparable...
If you are only actually comparing the keys then you can just use the .Keys property of the dictionary which returns an IEnumerable<TKey> that you can do your linq on...
eg:
var expectedOutput = newDic.Keys.Except(oldDic.Keys);
This does rely on the key being the same type but this goes without saying if you are comparing. Of course, there is nothing stopping you from converting their types first if you do wnat to do this with different types.
Also if you wanted to then get the values in one of the dictionaries you could do something like:
var newDicValues = expectedoutput.Select(x=>newDic[x]);
Or, you know, do any other linqy stuff you feel like. :)
Try this to get the difference between two different list: If they have any common property.
var differentItems = List<Type1>.Select(d => d.Name)
.Except(List<Type2>.Select(d => d.Name));
If understood correctly, try something like this
if you have a separate dictionary moething like this Dictionary<int, Fooclass> FinalDict
IEnumerable<int> list = OldDic.Keys.Except(NewDic.Keys);
foreach (var x in list)
{
var value =new MyClass();
OldDic.TryGetValue(x,out value );
FinalDict.Add(x,value);
}
So in the Dictionary called FinalDict will have the key and related Fooclass
Hope this helps

C# Lists: How to copy elements from one list to another, but only certain properties

So I have a list of objects with a number of properties. Among these properties are name and id. Let's call this object ExtendedObject. I've also declared a new List of different objects that have only the properties name and id. Let's call this object BasicObject.
What I'd like to do is convert or copy (for lack of better words) the List of ExtendedObject objects to a list of BasicObject objects. I know C# Lists have a lot of interesting methods that can be useful, so I wondered if there were an easy way to say something to the effect of:
basicObjectList = extendedObjectList.SomeListMethod<BasicObject>(some condition here);
But I realize it may end up looking nothing like that. I also realize that I could just loop through the list of ExtendedObjects, create a new BasicObject from each ExtendedObject's name and id, and push it onto a list of BasicObjects. But I was hoping for something a little more elegant than that.
Does anyone have any ideas? Thanks very much.
It depends on exactly how you'd construct your BasicObject from an ExtendedObject, but you could probably use the ConvertAll method:
List<BasicObject> basicObjectList =
extendedObjectList.ConvertAll(x => new BasicObject
{
id = x.id,
name = x.name
});
Or, if you prefer, you could use the LINQ Select method and then convert back to a list:
List<BasicObject> basicObjectList =
extendedObjectList.Select(x => new BasicObject
{
id = x.id,
name = x.name
}).ToList();
if you are on .NET 3.5 or greater this could be done by using LINQ projections:
basicObjectList = extendedObjectList.Select(x => new BasicObject { Id=x.Id, Name=x.Name})
var basicObjectList = extendedObjectList.Select(eo => new BasicObject { name = eo.name, id = eo.id });
I think that the OP's suggestion of "BasicObject" was just a pseudonym for a resulting object with a specific subset of properties from the original set. Anonymous types are your friend (as indicated by #mumtaz).
Assuming the following extendedObjectList if of IEnumerable<T> (including a List):
// "var" used so that runtime infers the type automatically
var subset = extendedObjectList
// you can use any Linq based clause for filtering
.Where(a => <conditions>)
// where the runtime creates a runtime anonymous type to describe your "BasicObject"
.Select(a => new { a.Property1, a.Property2, a.Property3 })
// conversion to a List collection of your anonymous type
.ToList();
At this point, subset contains a List of an anonymous (runtime) type that contains three properties - Property1, Property2, Property3.
You can manipulate this resulting list as follows:
// execute an anonymous delegate (method) for each of the new anonymous objects
subset.ForEach
(
basicObject =>
{
Console.WriteLine("Property1 - {0}", basicObject.Property1);
Console.WriteLine("Property2 - {0}", basicObject.Property2);
Console.WriteLine("Property3 - {0}", basicObject.Property3);
}
);
// grab the first object off the list
var firstBasicObject = subset.First();
// sort the anonymously typed list
var sortedSubset = subset.OrderBy(a => a.Property1).ToList();
Once the runtime has resolved the new object (of any combination of properties from the source object), you can use it virtually any way that you wish.
For Linq-to-Sql applications (using IQueryable<T>), the Select statement can be used to obtain specific column data (instead of the entire row), thereby creating an anonymous type to describe a subset of column data for a given row.

List to Anonymous Type in c#

The short story: I want to convert a list/dictionary into an anonymous object
Basically what I had before was:
var model = from item in IEnumerable<Item>
select new
{
name = item.Name
value = item.Value
}
etc.
If I have name, item.Name in a list or dictionary, how can I go about creating the same anonymous object model?
Edit: Clarification:
If the dictionary contains [name, item.Name] and [value, item.Value] as Key Value pairs, how would I go about creating the model without assuming that you know neither name nor value?
Since a List<T> implements IEnumerable<T> your existing code should work exactly the same way:
var model = from item in yourList
select new { name = item.Name };
For a Dictionary<TKey,TValue> you could simply do this:
var model = from item in yourDictionary
select new {
name = item.Key
value = item.Value
};
This works because Dictionary<TKey,TValue> implements IEnumerable<KeyValuePair<TKey,TValue>> so in the second expression item will be typed as KeyValuePair<TKey,TValue> which means you can project a new type using item.Key and item.Value.
It sounds like you just want to get the values from a dictionary? If so, MyDictionary.Values should do the trick for you.
If you want to construct, somewhere else, another anonymous object, that is type-compatible with the one you generate from your IEnumerable<Item>, you can do that by ensuring that the anonymous type you construct has:
The same number of members
Members with the same type
Members with the same name
... in the same order
If you do that, they will map to the same single generated type.
Now, why you would want to do that is beyond me, so I'm pretty sure I didn't understand your question. You should post more information about what you want to do.
Anyway, here's the code to produce an anonymous object that is type-compatible with the one from your IEnumerable:
var x = new
{
name = dict["name"],
value = dict["value"]
};
Since this obeys all the rules above, it will be of the same type as your objects generated from your Linq query.

Categories