I have a Dictionary that contains thread Information Dictionary<String,Thread>
"2FF"
"2IE"
"7CH"
etc
what i know is integers 2,7 etc what i want to know that in Dictionary how many strings contain the given integer if it is there then get that string
Eg
String GetString(int integer)
{
//if Dictionary contains given intgr return whole string in which that integer is present
}
}
With LINQ syntax:
var matchingThreads = from pair in dictionary
where pair.Key.StartsWith(number.ToString())
select pair.Value;
With traditional syntax:
var matchingThreads = dictionary
.Where(pair => pair.Key.StartsWith(number.ToString()))
.Select(pair => pair.Value);
If you only need to count them and you don't care about the Thread objects, you can use:
int count = dictionary.Keys.Count(key => key.StartsWith(number.ToString()))
Note that you need a using System.Linq directive.
Maybe a List<CustomClass> would be a better choice here where CustomClass would look like:
public sealed class CustomClass
{
public Thread Thread { get; set; }
public string String { get; set; }
}
(Better property names are alway good, of course :-) )
A dictionary is not sutitable if you do not know the exact keys or only parts of them.
You could then use LINQ to find out what you want, e.g.:
int count = list.Where(c => c.String.StartsWith(integer.ToString())).Count();
//or
IEnumerable<string> strings = list.Where(c => c.String.StartsWith(integer.ToString())).Select(c => c.String);
public IEnumerable<string> GetMatchingKeys(int value)
{
var valueText = value.ToString();
return _dictionary.Keys.Where(key => key.Contains(valueText));
}
Related
I wrote the code below to get all the values from a dictionary which has the given key.
Dictionary<string,string> _dictionary;
public List<string> GetValuesUsingKey(string key)
{
List<string> outp = new List<string>();
foreach(var d in _dictionary)
{
if (d.Key == key)
{
outp.Add(d.Value);
}
}
return outp;
}
is there a simpler way to achieve this result using LINQ?
Update :
it turned out that i was mislearned about Dictionaries, i though i could use multiple values for a single key but i was wrong
A key in a Dictionary is guaranteed to be unique, so there's no need to return a List.
public string GetValueUsingKey(string key)
{
bool isKeyPresent = _dictionary.TryGetValue(key, out var output);
return isKeyPresent ? output : _YOUR_DEFAULT_BEHAVIOUR_;
}
The big advantage of a Dictionary is that the time complexity for insertion and retrieval of values using the key is O(1); if you cycle through all the KeyValuePair it contains you completely nullify the purpose of using a Dictionary as it would make the retrieval O(n)!
Dictionary is a one to one map, you cannot have multiple values for a given key.
ILookup on the other hand supports this scenario, as well as null keys:
using System.Linq;
class Element
{
public string Key { get; }
public string Value { get; }
...
}
IEnumerable<Element> elements = ...
ILookup<string, string> lookup = elements.ToLookup(e => e.Key, e => e.Value);
and then to get your result:
List<string> outp = lookup[key].ToList();
I have a field that looks like:
public Dictionary<ClassA, List<ClassB>> MyDict;
Assume that:
public class ClassA
{
public string Name;
public int Id;
}
public class ClassB
{
public string Tag;
public string Text;
}
I'm trying to define a query that is of IEnumerable<KeyValuePair<ClassA,IEnumerable<ClassB>> type where I define a condition on the value of ClassB.Tag. I tried things like:
IEnumerable<KeyValuePair<ClassA,IEnumerable<ClassB>> q =
MyDict.Where(pair => pair.Value.Any(b => b.Tag == "a tag"));
But obviously the above is not what I need because it returns the whole List<ClassB> if any item matches that condition, while what I want is to return an IEnumrable or a List of items that match the condition.
dotNetFiddle demo
You need to construct the IEnumerable from a call to ToDictionary, where you use a projection to only take the matching BClass from the list and only take the result from that set where values in the BClass list were actually matched.
IEnumerable<KeyValuePair<ClassA,List<ClassB>>> q = MyDict.ToDictionary(
k => k.Key,
k => k.Value.Where(b => b.Tag == "10").ToList()
).Where(kv => kv.Value.Any());
I am using c# WPF for developing a Windows Application.
The application requires a class as follows
public class Limits
{
public String col1
{
get;
set;
}
public String col2
{
get;
set;
}
public String col3
{
get;
set;
}
}
I am using a List to Store Objects like:-
List myList<Limits> = new List<Limits>();
"myList" has around 15000 Objects.
Now, I want to search this myList for a particular attribute.
Eg: I want to find out the object that has col1 set as "abc".
How can I use Binary Search for this problem?
First of all, the list has to be sorted on the col1 property for you to be able to use binary search at all.
You would need a comparer that compares the col1 property:
public class LimitsComparer : IComparer<Limits> {
public int Compare(Limits x, Limits y) {
return x.col1.CompareTo(y.col1);
}
}
Then you can use that to do the binary search:
int index = myList.BinarySearch(new Limits { col1 = "abc" }, new LimitsComparer());
The index returned is:
The zero-based index of item in the sorted List, if item is found;
otherwise, a negative number that is the bitwise complement of the
index of the next element that is larger than item or, if there is no
larger element, the bitwise complement of Count.
You can also use the Where method to get the objects that has that property:
List<Limits> result = myList.Where(x => x.col1 == "abc").ToList();
Although that is not quite as efficient, you should still consider if that is a better solution as it's easier to implement and gives a result that is easier to handle. Also (and this might be more important), it works even if the list isn't sorted on col1.
You could use somthing like this.
myList.Where(i => i.col1 == "abc").ToList();
Use a dictionary where the keys are stored in a hash table. Linq will create the cdictionary easily.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication41
{
class Program
{
static void Main(string[] args)
{
List<Limits> myList = new List<Limits>();
//dictionary with unique keys
Dictionary<string, Limits> dict1 = myList.AsEnumerable()
.GroupBy(x => x.col2, y => y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
//dictionary with keys having multiple values
Dictionary<string, List<Limits>> dict2 = myList.AsEnumerable()
.GroupBy(x => x.col2, y => y)
.ToDictionary(x => x.Key, y => y.ToList());
Limits abc = dict1["abc"];
}
}
public class Limits
{
public String col1 { get; set; }
public String col2 { get; set; }
public String col3 { get; set; }
}
}
unless you explicitly want to use binary search, you should use the standard Linq functions available to you. Unless your list is already sorted, this might be more efficient than binary sort.
var myList = new List<Limits> {....}
var entry = myList.Where(l => l.col1== "abc").FirstOrDefault();
if(entry == null)
{ // no match found }
If you really want binary search, ref Can LINQ use binary search when the collection is ordered?
I have this:
public class GraphicsDraw
{
public Dictionary<int,GraphicItem> items { get; set; }
}
public abstract class GraphicItem
{
public float ItemSize { get; set; }
}
And I can access to all ItemSize's like this:
{
GraphicsDraw gd = new GraphicsDraw();
gd.items[i].ItemSize;
}
Is there any nice way that I can list ItemSize's down separately in another dictionary whit same key and ItemSize values?
Dictionary<int, float> ItemSize = items.(???)
Sure, using ToDictionary:
items.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ItemSize);
You can do, which uses LINQ,
Dictionary<int,float> itemSizes =
items.ToDictionary(item => item.Key, item => item.Value.ItemSize);
The ToDictionary accepts two delegates (or lambda expressions), the first one to select the key and the second one to select the value of the dictionary.
In your case you want to keep the same key, but change the value to the ItemSize property, thus the second expression.
You can simple use LINQ to extract necessary keys and values from items property.
items.ToDictionary(x => x.Key, x => x.Value.ItemSize);
I have a file with lines of string. Each line represent a collection of key value, for example:
Name=JUI;Type=HomeUser;Address=Belgium;Address=Liege;Address=Street
Name=Tim;Type=HomeUser;Address=Belgium;Address=Hasselt;Address=Street
Name=Kim;Type=Proff;Address=Germany;Address=Dusseldorf;Address=Street
Name=Ils;Type=Proff;Address=Germany;Address=Munich;Address=Street
Name=Jan;Type=Student;Address=Germany;Address=Frankfurt;Address=Street
Name=Dav;Type=Student;Address=France;Address=Mitz;Address=Street
Name=Soli;Type=HomeUser;Address=France;Address=Lyon;Address=Street
Name=Mik;Type=HomeUser;Address=Switzerland;Address=Zurich;Address=Street
Name=Peter;Type=Blocked;Address=Netherland;Address=Enschede;Address=Street
Name=Maz;Type=Blocked;Address=Germany;Address=Achen;Address=Street
Name=Jo;Type=Teacher;Address=Belgium;Address=Antwerpen;Address=Street
How can I do the following:
Get the names where type is HomeUser
Get the types where Address =Germany (problem there are 3 address key in earch line)
Get the name where address =Lyon
Is there is a simple way to do that?
In all of these cases, the answer is really simple when you've got a better data representation - you can just use LINQ.
However, the first step will be to parse the data. Model it something like this:
public class User // ???
{
public string Name { get; private set; }
public string Type { get; private set; } // Should this be an enum?
public IList<string> Addresses { get; private set; }
// Could make this a constructor if you really want... I like the
// explicit nature of the static factory method.
public static User ParseLine(string line)
{
// TODO: Split line into components etc
}
}
One you've got a List<User> your queries will be really easy - but it's important to separate "put data into a more natural representation" from "do interesting operations with data".
This is a much more general point than just this particular example, but always try to get your data into a natural, useful representation as early as you can, and then keep it in that representation for as long as you can. Only deal with an awkward representation (typically a string) at the boundaries of your code, if possible.
Create a Regex to parse the item: "Name=(.+?);Type=(.+?);Address=(.+?) etc."
Then you could create a class to hold all the information
class Record { public string Name; public string Type; public string Address; public string Address2; public string Address3}
then match each line with the regex, fill the fields from Match groups and create an instance of the class and add these to a List<Record> records.
Now you can easily search with linq for:
type is HomeUser : records.Where(p=>p.Type=="HomeUser")
Address is Germany : records.Where(p=>p.Address=="Germany")
Address is Lyon: records.Where(p=>p.Address=="Lyon")
you could easily extend this example to look in all 3 address fields
It would be easier to first define a struct
struct MyStruct
{
public string Name, Type /* etc.*/ ;
}
After that you'll need to split your input
string[] arrayOfInputs = inpuString.Split(new char[]{Environment.NewLine, '\n', '\r'}) // splits your input, such that every element represents a line
List<MyStruct> myStruct = new List<MyStruct>;
foreach (string s in arrayOfInputs)
{
string[] arrayOfFields = s.Split(';');
// arrayOfFields[0] == "Name=name"
// arrayOfFields[1] == "Type=type"
// etc. extract needed info
myStruct.Add(new MyStruct(/* arguments go here */))
}
Now that you have extracted your data and put them into a list of structs, you may search for the required data using Linq
string theNameImLookingFor = from element in myStruct
where element.Type == "HomeUser"
|| element.Address[0] == "Lyon"
|| element.Address[1] == "Lyon"
|| element.Address[2] == "Lyon"
select element.Name;
string theTypeImLookingFor = from element in myStruct
// etc.
select element.Type;
Alternatively you can do it like this:
string tNILF = myStruct.Where(element => element.Type == "HomeUser" /* || etc. */).Select(element => element.Name);
One way to do this is to read the key-value pairs into a collection of dynamic objects. Once this is done, you can use the dynamic runtime to query the dynamic objects using LINQ:
To create a collection of dynamic objects:
var users = str.Split("\r\n".ToArray(), StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Split(';')
.Select(p => p.Split('='))
.ToLookup(s => s[0], s => s[1])
.ToDictionary(l => l.Key, l => (l.Count() > 1)
? (object)l.ToList() : (object)l.First())
.ToExpando());
Note the use of this extension method:
public static dynamic ToExpando(this IDictionary<string, object> dict)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (var kv in dict)
expando[kv.Key] = kv.Value;
return expando;
}
Then you can run the queries you're interested in:
1.Get the names where type is HomeUser:
var homeUsers = users.Where(u => u.Type == "HomeUser")
.Select(u => u.Name);
2.Get the types where Address =Germany (Note: .Address is a List<string>):
var typesInGermany = users.Where(u=>u.Address.Contains("Germany"))
.Select(u => u.Type).Distinct();
3.Get the name where address =Lyon:
var namesInLyon = users.Where(u => u.Address.Contains("Lyon"))
.Select(u => u.Name);