Query dictionary with linq - c#

I have a dictionary that gets built which is below
Dictionary<string, string> GTNMobilelist = new Dictionary<string, string>();
GTNMobilelist = LoadMobileNumbers();
i then need to query the Dictionary to check if a mobile number that has been enetered in to a textbox exists within the dictionary "Hope that makes sense" :-/
this is what i have
foreach (GridViewRow HandSetRow in grdvHandSets.Rows)
{
TextBox txtmobileNumber = (TextBox)HandSetRow.FindControl("txtmobilenumber");
//I need the linq statement here if the mobile number doesnt exists i need to
//throw an error saying mobile number doesnt exist within the dictionary
//iv been looking at linq statements for the past hour and im confused :(
}
Can any one help me on a quick solution for this?

There is no point using LINQ here. Use ContainsKey or ContainsValue instead.
if (!GTNMobilelist.ContainsValue(txtmobileNumber.Text))
ShowErrorMessage();

Next time, post your code so far, then we can point out any errors.
It is not clear to me if the phone number is in the key or in the value, but something like this should work.
Check by key:
string phoneNumberToLookFor = "12345678";
bool phoneNumberExists = GTNMobilelist.Any(kvp => kvp.Key == phoneNumberToLookFor);
Or, check by value:
string phoneNumberToLookFor = "12345678";
bool phoneNumberExists = GTNMobilelist.Any(kvp => kvp.Value == phoneNumberToLookFor);

Related

Searching dictionary for matching key from a textbox C#

I'm reading a csv file that contains abbreviations and the full version for example LOL,Laughing out Loud. I've created a dictionary where the abbreviation is the key and full version is the value.
'''
private void btnFilter_Click(object sender, RoutedEventArgs e)
{
var keys = new List<string>();
var values = new List<string>();
using (var rd = new StreamReader("textwords.csv"))
{
while (!rd.EndOfStream)
{
var splits = rd.ReadLine().Split(',');
keys.Add(splits[0]);
values.Add(splits[1]);
}
}
var dictionary = keys.Zip(values, (k, v) => new { Key = k, Value = v }).ToDictionary(x => x.Key, x => x.Value);
foreach (var k in dictionary)
{
//
}
aMessage.MessageContent = txtContent.Text;
}
'''
I'm using a button that will check if the textbox txtContent contains any of the abbreviations in the text and change this to the full version. So if the textbox contained the following. "Going to be AFK" after the button click it would change this to "Going to be away from keyboard".
I want to write a foreach loop that would check for any abbreviations, elongate them and then save this to a string variable MessageContent.
Would anyone be able to show me the best way to go about this as I'm not sure how to do this with the input from a textbox?
Thanks
You can just use LINQ to read and create a dictionary object:
var dictionary = File.ReadAllLines(#"textwords.csv")
.Select(x => x.Split(",",StringSplitOptions.RemoveEmptyEntries))
.ToDictionary(key => key.FirstOrDefault().Trim(),
value => value.Skip(1).FirstOrDefault().Trim());
If the abbrevs are correct, i.e. you don't need fuzzy logic, you can use a variety of .NET objects and search the keys rather quickly.
if(dict.ContainsKey(myKey))
{
}
I did that freehand, so it might be dict.Keys.Contains() or similar. The point is you can search the dictionary directly rather than loop.
If you need to do a more fuzzy search, you can utilize LINQ to write queries to iterate over collections of objects extremely fast (and few lines).
As for yours, you would iterate over dictionary.Keys to seach keys, but I still don't see why you need the extra code.

Get all Keys from a MultiDictionary

Im looking for a way to get all FIRST level Keys of a multiDictionary and im totaly unable to get them (its for debugging purpose)
i declared the dictionary like this :
private Dictionary<string, Dictionary<string, Packet>> PacketsStore = new Dictionary<string, Dictionary<string, Packet>>();
So how can i print out a list of all the base keys?
how could i then print out the second level keys incase i need it too later...
thanks in advance!
First level, the well-known way:
var allKeys = PacketsStore.Keys;
Sub-dictionary keys, the LINQ way:
var allSubKeys = PacketsStore.SelectMany(pair => pair.Value.Keys);
OP has commented out on other answer that the two nested foreach loops were more suitable for debugging purposes, but, after all, if OP wants to output all subkeys to console, it can still be done with a one-liner solution:
// One-liner solution!
PacketsStore.SelectMany(pair => pair.Value.Keys).ToList().ForEach(Console.WriteLine);
foreach(KeyValuePair<string, Dictionary<string, Packet>> entry in PacketsStore)
{
string key = entry.Key; // first level
foreach(KeyValuePair<string, Packet> entryInner in entry.Value)
{
string keyInner = entryInner.Key // second level
}
}
I have taken keys into variables you can take the same into some collection. Purpose was to get keys :)
For all keys, try:
var keys = PacketsStore.Keys.ToArray();
and for second level keys:
List<string> secondaryKeys;
foreach (var key in keys)
{
secondaryKeys.AddRange(PacketStore[key].Keys.ToArray());
}

How to sort a list of objects by a property

I've got this chunk of code:
DataTable dt = new DataTable();
dt.Columns.Add("Status");
dt.Columns.Add("File");
dt.Columns.Add("Revision");
int i = 0;
foreach (SvnStatusEventArgs status in statuses) // statuses is a Collection
{
dt.Rows.Add();
switch (status.LocalContentStatus)
{
case SvnStatus.NotVersioned:
dt.Rows[i]["Status"] = "Not Versioned";
break;
default:
dt.Rows[i]["Status"] = status.LocalContentStatus.ToString();
break;
}
dt.Rows[i]["File"] = status.Path;
foreach(SvnInfoEventArgs info in infos) //infos is a Collection
{
if (status.Path.Equals(info.Path))
{
dt.Rows[i]["Revision"] = info.Revision;
break;
}
}
i++;
}
statuses and infos can have up to 20K rows each, however, so my nested foreach could take a long time.
I thought I could maybe speed this up if I converted these Collections to Lists and then try to Sort them both by Path.
Looking over the MSDN Page for the Sort method, I have no idea how I'd go about comparing the Path field from SvnStatusEventArgs[n] and SvnStatusEventArgs[n+1]. Then I also started to wonder, since I'd be iterating in their entirety over both of these groups of objects and sorting them anyways, would that really be any more efficient than my existing code? I suppose it would be n*2 as opposed to n*n, right?
For what it's worth, the Path field I'm trying to sort by is just a string.
You could create a Dictionary<string, int>(the key is the path and the value the revision).
Dictionary<string, int> pathRevisions = infos
.GroupBy(info => info.Path)
.ToDictionary(group => group.Key, group => group.First().Revision);
....
in the loop:
int revision;
if(pathRevisions.TryGetValue(status.Path, out revision))
dt.Rows[i].SetField("Revision", revision);
Your question was fairly unclear but since you said in the comments this is what you meant
foreach (SvnStatusEventArgs status
in statuses
.OrderBy(x => x.Path))
This is a very basic approach though. If you want a more optimal one you should use Tim Schmelter's solution.
The best would just be to make a dictionary on infos - with key as path. That would be the most efficient overall.

GetCookie extract information to a String

I'm trying to get the numbers information from a cookie I get by Set-Cookie I need &om=-&lv=1341532178340&xrs= the numbers here
This is what I came up with:
string key = "";
ArrayList list = new ArrayList();
foreach (Cookie cookieValue in agent.LastResponse.Cookies)
{
list.Add(cookieValue);
}
String[] myArr = (String[])list.ToArray(typeof(string));
foreach (string i in myArr)
{
// Here we call Regex.Match.
Match match = Regex.Match(i, #"&lv=(.*)&xrs=",
RegexOptions.IgnoreCase);
// Here we check the Match instance.
if (match.Success)
{
// Finally, we get the Group value and display it.
key = match.Groups[1].Value;
}
}
agent.GetURL("http://site.com/" + key + ".php");
The issue I'm having is I cannot change ArrayList to String (the error is: "At least one element in the source array could not be cast down to the destination array type."), I thought you guys can help me maybe you can come up with a way to fix it or a better code to do that?
Thanks a lot!
With first loop, you are building an ArrayList that contains Cookie instances. It's not possible to simply convert from Cookie to string as you are attempting to do just before the second loop.
A simple way to get values of all cookies is to use LINQ:
IEnumerable<string> cookieValues = agent.LastResponse.Cookies.Select(x => x.Value);
If you are still using .NET Framework 2.0, you will need to use a loop:
List<string> cookieValues = new List<string>();
foreach (Cookie cookie in agent.LastResponse.Cookies)
{
cookieValues.Add(cookie.Value);
}
Then, you can iterate over this collection just like you previously were. However, are you aware that if multiple cookies match your regex, the last one that matches will be stored to the key? Don't know how exactly you want this to work when there are multiple cookies that match, but if you simply want the first one, you can again employ LINQ to make your code simpler and do almost everything you need in a single query:
var cookies = agent.LastResponse.Cookies;
string key = cookies.Cast<Cookie>()
.Select(x => Regex.Match(x.Value, #"&lv=(.*)&xrs=", RegexOptions.IgnoreCase))
.Where(x => x.Success)
.Select(x => x.Groups[1].Value)
.FirstOrDefault();
If there was no match, the key will be null, otherwise, it will contain the first match.
The Cast<Cookie>() bit is necessary for type inference to kick in - I believe that agent.LastResponse.Cookies returns an instance of CookieCollection which does not implement IEnumerable<Cookie>.

is there a way to get the Order number of a Dictionary Item?

Dictionary<string,string> items = new Dictionary<string,string>();
IEnumerable<string> textvalues = from c in......//using linQ to query
string s = textvalues[items["book"]];
In this case the textvalues array will accept a integer value to return the string value.How can i get the item number , say "items" has 5 itemnames and "book" is at first position then i must get 0.So textvalues[items["book"]] would be translated as textvalues[item[0]]
Ok i was trying to use OpenXML 2.0 to read Excel.The point here is there is no way i could specify a field name and get the value.
So i was trying to iterate the first row of a worksheet, add the values to a dictionary Dictionary fieldItems so that when i say fieldItems["Status"] it would retrieve me the cell value based on the column number , in my case the column header name.ok here's the code for it.
Dictionary<string, int> headers = new Dictionary<string, int>();
IEnumerable<string> ColumnHeaders = from cell in (from row in worksheet.Descendants<Row>()
where row.RowIndex == 1
select row).First().Descendants<Cell>()
where cell.CellValue != null
select
(cell.DataType != null
&& cell.DataType.HasValue
&& cell.DataType == CellValues.SharedString
? sharedString.ChildElements[
int.Parse(cell.CellValue.InnerText)].InnerText
: cell.CellValue.InnerText);
int i=0;
Parallel.ForEach(ColumnHeaders, x => { headers.Add(x,i++); });
order.Number = textValues[headers["Number"]];
(Darn, I didn't misread it after all, and there's no edit history in the first five minutes.)
Your question is somewhat confusingly presented... but it seems like you're basically trying to find the "position" of an item within a dictionary. There's no such concept in Dictionary<TKey, TValue>. You should regard it as a set of mappings from keys to values.
Obviously when you iterate over the entries in that set of mappings they will come out in some order - but there's no guarantee that it will bear any relation to the order in which the entries were added. If you use SortedDictionary<,> or SortedList<,> (both of which are really still dictionaries), you can get the entries in sorted key order... but it's not clear whether that would be good enough for you.
It's also not clear what you're really trying to achieve - you call textvalues an array in the text, but declare it as an IEnumerable<string> - and it looks like you're then trying to use an indexer with a string parameter...
EDIT: Okay, now the question has been edited, you've got a Dictionary<string, int> rather than a Dictionary<string, string>... so the whole thing makes more sense. Now it's easy:
order.Number = textValues.ElementAt(headers["Number"]);

Categories