Linq with a Dictionary inside the class - c#

i have the next class:
public class Example
{
String name;
Dictionary<String, decimal> data;
public Example()
{
data = new Dictionary<String, decimal>();
}
}
Then, using Linq i need to retrieve all distinct String keys in the data field.
For example:
e1: 1 - [["a", 2m],["b",3m])
e2: 2 - [["b", 2m],["c",3m])
I'll need a list with: ["a","b","c"]
I hope I was clear enough.
Thanks.
PD: One thing i was missing, i have a List of Examples.

Assuming you mean you have a collection of Examples (e1, e2...):
var keys = examples.SelectMany(example => example.data.Keys)
.Distinct();

var keys =
(from ex in examples
from key in ex.Data.Keys
select key).Distinct();

Related

Linq expression to join a list and a dictionary

I have a list of part numbers:
var parts = new List<string> {"part1", "part2", "part3"};
I also have a dictionary of quantities for these part numbers:
var quantities = new Dictionary<string, int> {{"part1", 45}, {"part3", 25}};
Given a delimiter of |, I need to arrange these values in a flat file like so:
SalesRep|part1|part2|part3
Mr. Foo|45||25
What I'd like to do is define a string that no matter what values are in parts and quantities, I can tack this on to the sales rep name to resemble the example above.
It seems like I should be able to do this with a string.Join() on an enumerable LINQ operation, but I can't figure out what statement will get me the IEnumerable<string> result from joining parts and quantities. It thought that would be a .Join(), but the signature doesn't seem right. Can someone enlighten me?
Something like this perhaps?
var partValues = parts.Select(x => quantities.ContainsKey(x) ? quantities[x] : 0);
Basically for each item in the parts list you either pick the value from your dictionary, or if it doesn't exist 0.
To make this a little more interesting you could define a generic extension method on IDictionary<T,U> that makes this a little more readable:
public static class DictionaryExtensions
{
public static U GetValueOrDefault<T,U>(this IDictionary<T, U> dict, T key)
{
if(dict.ContainsKey(key))
{
return dict[key];
}
return default(U);
}
}
Then you can simply write:
var partValues = parts.Select(quantities.GetValueOrDefault);
var parts = new List<string> { "part1", "part2", "part3" };
var quantities = new Dictionary<string, int> { { "part1", 45 }, { "part3", 25 } };
var result = string.Join("|",
from p in parts select quantities.ContainsKey(p)
? quantities[p].ToString() : "");

Suggested structure to maps some strings to some other strings

In my console application I have one hundred county codes and their names. For example:
"01" : "Floyd"
"02" : "Wabash"
When my program uses the values, it reads "01","02"...and I want to get "Floyd", etc...
This list won't grow in future, I am just hard coding them, How do you suggest to access these?
Maybe in a static class? Maybe in a JSON format? Other ways?
Dictionary is what you look for: MSDN link
Short example:
void Main()
{
var dic = new Dictionary<int,string>();
// Instead of having a method to check, we use this Action
Action<int> tryDic = (i) => {
if (dic.ContainsKey(i))
Console.WriteLine("{0}:{1}", i, dic[i]);
else
Console.WriteLine("dic has no key {0}", i);
};
dic.Add(1,"one");
dic.Add(2,"two");
// dic.Keys = 1, 2
// dic.Values = one, two
tryDic(1); // one
tryDic(3); // dic has no key 3 (Happens in Action above)
dic[1]="wow";
tryDic(1); // wow
}
Just use a simple Dictionary<string, string>; if you really want you can wrap it in a class to add some behavior such as handling keys not found, or already existing
You are looking for a Dictionary<string, string>
var values = new Dictionary<string,string>();
values.Add("01", "Floyd");
...
var value = values["01"]; // Floyd

BinarySearch in two dimensional list

I have dimensional list:
List<List<string>> index_en_bg = new List<List<string>>();
index_en_bg.Add(new List<string>() { word1, translation1 });
index_en_bg.Add(new List<string>() { word2, translation2 });
index_en_bg.Add(new List<string>() { word3, translation3 });
I would do binary search by the first column (words), something like this:
int row = index_en_bg.BinarySearch(searchingstr);
but it works only for a one-dimensional list. How would I extend it to work for two-dimensional lists in my case? I don't want to use Dictionary class.
In this case you need to provide your own customer IComparer-implementing comparator
public class Comparer: IComparer<IList<string>>
{
public int Compare(IList<string> x, IList<string> y)
{
// base the comparison result on the first element in the respective lists
// eg basically
return x[0].CompareTo(y[0]);
}
And you'll call it like this, offering a List where only the field you're searching is filled in.
int row = index_en_bg.BinarySearch(new List<string>() {searchingstr},new Comparer());
Well as far as I understand you should use Dictionary<K,V> instead, this way:
// 1 creating the dictionary
var dic = new Dictionary<string, string>();
dic["word1"] = "translation1";
dic["word2"] = "translation2";
dic["word3"] = "translation3";
// 2 finding a translation
var trans = dic["word1"];
And Dictionary<K,V> is really performant.
But if you insist on using BinarySearch you can implement IComparer<List<string>> and pass it to the function.
As you always search using the first item of the list you could use dictionary too.
var d = Dictionary<string, List<string>>();
as answered previously it's preforms much better than List.

Is there a more efficient way to convert LINQ result to string[] or List<string>?

I'm looking for a way to convert the result of my Linq query to a string[] or List without the usual loop method. In case you are wondering "Examples are fine, but what are you really trying to do?" I'm trying to do what the example shows; I have a collection of objects and I want a string array or list of the unique IDs that are contained within the list of objects.
I think the code example says it all. It's a complete program you can run.
using System.Collections.Generic;
using System.Linq;
class Program
{
class DataModel
{
public DataModel(string id) { ID = id; }
public string ID;
}
static void Main(string[] args)
{
var dummyData = new DataModel[]
{
new DataModel("1"),
new DataModel("1"),
new DataModel("2"),
new DataModel("3"),
new DataModel("3")
};
// This works fine
var uniqueIDs =
from model in dummyData
group model by model.ID into grouped
select grouped.Key;
// This is the part that bugs me, it's so inelegant...
List<string> idStringList = new List<string>();
foreach (var id in uniqueIDs)
idStringList.Add(id);
}
}
you are just looking for ToList():
idStringList = uniqueIDs.ToList();
If you just want the list, you can also add this to the query directly:
var idStringList = (from model in dummyData
group model by model.ID into grouped
select grouped.Key).ToList();
var list = whatever.ToList();
What usual loop method?
Why not just uniqueIDs.ToList(); This is an extension method on IEnumerable. Here is the MSDN
You could do the whole operation in one line:
List<string> uniqueIDs = dummyData.Select(model => model.ID).Distinct().ToList();
the ToArray() method works similarly but will provide an array.
There are numerous extension methods on IEnumerable you can make use to achieve this like
whateverList.ToList()
whateverList.ToArray()
If you really want an array string[], you can do
string[] myArray = (from model in dummyData
group model by model.ID into grouped
select grouped.Key.ToString()).ToArray();

Picking a collection for my data

I have to load and use my data from a db. The data is represented like this:
group_id term
1 hello
1 world
1 bye
2 foo
2 bar
etc.
What is a good C# collection to load and use this data?
Looks like you need a Dictionary<int, List<string>>:
var dict = new Dictionary<int, List<string>>();
var dict.Add(1, new List<string> { "hello", "world", "bye" });
var dict.Add(2, new List<string> { "foo", "bar" });
It all depends on what you have to do with the collection but it seems like Lookup is a good candidate in case you need to group by group_id.
If your data is in a datatable:
var lookup = table.AsEnumerable().ToLookup(row => row.Field<int>("group_id"));
and then access the groups the following way:
foreach (var group in lookup)
{
int groupID = group.Key;
IEnumerable<DataRow> groupRows = group;
}
It depends very strongly on what you need to do with your data.
If you just need to list your data, create a class which holds the data and use a List<Vocable>.
public class Vocable
{
public int Group { get; set; }
public string Term { get; set; }
}
List<Vocable> vocables;
If you need to look up all terms belonging to a group, use a Dictionary<int, List<string>> using the group id as key and a list of terms as value.
If you need to look up the group a term belongs to, use a Dictionary<string, int> using the term as key and the group id as value.
To load and save data from and to a DB you can use the DataSet/DataTable/DataRow classes.
Look at DataAdapter etc. depends on your database server (MySQL, MsSQL, ...)
if you want to work with objects i suggest you the ORMs EntityFramework (Microsoft) or SubSonic.
http://subsonicproject.com/docs/The_5_Minute_Demo
with an ORM you can use LINQ Queries like this:
// Define a query that returns all Department
// objects and course objects, ordered by name.
var departmentQuery = from d in schoolContext.Departments.Include("Courses")
orderby d.Name
select d;

Categories

Resources