I've two dictionaries as following:
Dictionary 1:
Dictionary<string, string> dict1 = new Dictionary<string, string>();
request.Add("key1", "value1");
request.Add("key2", "value2");
request.Add("key3", "value3");
Dictionary 2 :
Dictionary<string, string> request = new Dictionary<string, string>();
request.Add("key1", "value1");
request.Add("key2", "value2");
I need to compare above two dictionaries using LINQ query with condition:
1) All keys in dict2 should match with keys in dict1
2) The matched keys should have equivalent value
3) Even if the value of key2 in dict2 is empty, it should match
Help on above in appreciated. Thanks in advance.
Regards,
Sachin
You could use the Contains method and provide a custom IEqualityComparer, but an easier way would be to use Any():
var dict1 = new Dictionary<string, string>
{
{"key1", "value1"},
{"key2", "value2"},
{"key3", "value3"}
};
var dict2 = new Dictionary<string, string>
{
{"key1", "value1"},
{"key2", "value2"}
};
dict2.All(k2 =>
dict1.Any(k1 => k1.Key == k2.Key &&
(String.IsNullOrEmpty(k2.Value) || k1.Value == k2.Value)))
I guess with empty you mean null or an empty string, hence I used String.IsNullOrEmpty. If you want to just check for null, do a simple k2.Value == null instead.
Related
I have the below dictionary
Dictionary<string,string> q1=new Dictionary<string,string>
{
{"h1","name1"},{"h2","name2"}
};
Dictionary<string,string> q2=new Dictionary<string,string>
{
{"h1","name12"},{"h2","name23"}
};
Dictionary<string,string> q3=new Dictionary<string,string>
{
{"h1","name123"},{"h2","name234"}
};
List<Dictionary<string,string>> m1 = new List<Dictionary<string,string>> { q1,q2,q3 };
Dictionary<string, List<Dictionary<string,string>>> mhi = new Dictionary<string, List<Dictionary<string,string>>>();
mhi.Add("x1", m1);
I need to return a list which has the values name1,name12,name123 using linq.
I am aware of normal method which works for me. But I am curious to know how to implement this using linq
Try this:
var q1 = new Dictionary<string, string> {
{"h1", "name1"},
{"h2", "name2"}
};
var q2 = new Dictionary<string, string> {
{"h1", "name12"},
{"h2", "name23"}
};
var q3 = new Dictionary<string, string> {
{"h1", "name123"},
{"h2", "name234"}
};
var m1 = new List<Dictionary<string, string>> { q1, q2, q3 };
//Using LINQ
List<string> result = (from dictionary in m1
from keyValuePair in dictionary
where keyValuePair.Key == "h1"
select keyValuePair.Value).ToList();
//result = name1,name12,name123
//without linq
var result2 = new List<string>();
foreach(var dictionary in m1)
foreach(var keyValuePair in dictionary)
if(keyValuePair.Key == "h1")
result2.Add(keyValuePair.Value);
Edit:
The from clause specifies the data source, the where clause applies the filter, and the select clause projects each element of the sequence into a new form.
Linq queries are not executed until we iterate through it. (Here .ToList() is doing that). It's like a blueprint which specifies how the information is returned when executed(iterated).
Lets examine each statement separately:
from dictionary in m1 - This is much like foreach(var dictionary in m) except that it doesn't iterate (Because its a blueprint). It specifies which source we are iterating through (m1) and the variable to assign to each member (dictionary that is. We know that it will be of type Dictionary<String, String>)
from keyValuePair in dictionary - Here we use the dictionary variable created from the previous statement. The type of keyValuePair will be KeyValuePair<string,string> because we will be "iterating" through a Dictionary<string,string> when the query is executed.
where keyvaluePair.Key == "h1" - This filters out the keyValuePairs from the previous statement whose Key property equals "h1".
Now that we filtered out the KeyValuePairs, we can select their Value property. This "projects" the filtered out KeyValuePair sequence to the new type IEnumerable<string>
Finally, ToList method executes the query to get the results.
I want to get a particular datacoulmn values into string by appending each row values.
I have a below code which will return into string array, and then i use foreach to append each string to one string
string[] strs = ds.Tables[0].AsEnumerable().Select(s => s.Field<string>("name")).ToArray<string>();
StringBuilder sb = new StringBuilder();
foreach(string str in strs)
{
sb.Append(str);
}
can this be replaced into LINQ query which will return result in string?
You can use String.Join to join these together directly, which also eliminates the need to create the temporary array:
var result = string.Join("", ds.Tables[0].AsEnumerable().Select(s => s.Field<string>("name")));
There is a scenario in which I am sending an HTTP request and getting this response String from the server.
submitstatus: 0
smsid: 255242179159525376
var streamResponse = newStreamReader(response.GetResponseStream()).ReadToEnd().ToString();
I want to extract the key values by using LINQ. New to LINQ any suggestions.
I am using output string to simulate the result
string output = #"submitstatus: 0
smsid: 255242179159525376";
// you can use regex to match the key/value
// what comes before `:` will be the key and after the value
var matches = Regex.Matches(output, #"(?<Key>\w+):\s(?<Value>[^\n]+)");
// for each match, select the `Key` match as a Key for the dictionary and
// `Value` match as the value
var d = matches.OfType<Match>()
.ToDictionary(k => k.Groups["Key"].Value, v => v.Groups["Value"].Value);
So you will have a Dictionary<string, string> with keys and values.
Using Split method
var keysValues = output.Split(new string[] { ":", "\r\n" },
StringSplitOptions.RemoveEmptyEntries);
Dictionary<string, string> d = new Dictionary<string, string>();
for (int i = 0; i < keysValues.Length; i += 2)
{
d.Add(keysValues[i], keysValues[i + 1]);
}
Trying to use purely Linq
var keysValues = output.Split(new string[] { ":", "\r\n" },
StringSplitOptions.RemoveEmptyEntries);
var keys = keysValues.Where((o, i) => (i & 1) == 0);
var values = keysValues.Where((o, i) => (i & 1) != 0);
var dictionary = keys.Zip(values, (k, v) => new { k, v })
.ToDictionary(o => o.k, o => o.v);
Why dont you use regex? Smth like:
(?<=submitstatus:\s)\d+
for submitstatus
and
(?<=smsid:\s)\d+
for smsid
I want to get random value of HashMap, but only from one key.
This is how i build my HashMap. Every Key has multiple values.
ArrayList<HashMap<String, String>> items = new ArrayList<HashMap<String, String>>();
for (.....) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
map.put(KEY_1, parser.getValue(e, KEY_1));
map.put(KEY_2, parser.getValue(e, KEY_2));
// adding HashList to ArrayList
items.add(map);
}
So key "KEY_1" has multiple values so do "KEY_2".
Now i want to get random value using key "KEY_1". How to do that ?
EDIT: I think i know where is problem, although dont know yet how to fix that.
Problem is defining size(); I need somehow get size not from all HashMap items like "items.size();" but something more similar to "items.KEY_1.size();"
With this code getting NullPointerException
int index = random.nextInt(items.size());
HashMap<String, String> randomitem = new HashMap<String, String>();
randomitem = items.get(index);
System.out.println(randomitem.get(KEY_1));
With this code im able to get value not random:
int index = 2;
HashMap<String, String> randomitem = new HashMap<String, String>();
randomitem = items.get(index);
System.out.println(randomitem.get(KEY_1));
EDIT: With this code i can get random values but i get values from all keys. How to get values only from one key ?
Random rand = new Random();
indexx = rand.nextInt(items.size());
System.out.println(items.get(indexx));
Solved With this code i can get random value from certain key.
Random rand = new Random();
indexx = rand.nextInt(items.size());
HashMap<String, String> randomitems = items.get(indexx);
System.out.println(randomitems.get(KEY_1));
I have the following code that does what I want however I was wondering if there was a way to do the same thing directly from a linq query.
XElement xmlData = XElement.Parse(items.Xml);
var itemsNotSynched =
(from a in xmlData.Descendants(XName.Get("row", "#RowsetSchema"))
group a by new
{
employeeID = (string)a.Attribute("ows_EmployeeID"),
courseID = (string)a.Attribute("ows_CourseID"),
title = (string)a.Attribute("ows_LinkTitle")
} into ex
select new
{
ex.Key.title,
ex.Key.courseID,
ex.Key.employeeID
} into eb
select eb).ToArray();
List<Dictionary<string, string>> list = new List<Dictionary<string, string>>();
foreach(var item in itemsNotSynched)
{
Dictionary<string, string> itm = new Dictionary<string, string>();
itm.Add("employeeID", item.employeeID.ToString());
if(item.courseID != null)
{
itm.Add("courseID", item.courseID.ToString());
}
itm.Add("title", item.title.ToString());
list.Add(itm);
}
Thanks in advance,
-EC-
Edit 1.
I managed to get what I wanted with using the suggestion from SLaks... I'll give it another shot at the .Distinct()
XElement xmlData = XElement.Parse(items.Xml);
List<Dictionary<string,string>> itemsNotSynched =
(from a in xmlData.Descendants(XName.Get("row", "#RowsetSchema"))
group a by new
{
employeeID = (string)a.Attribute("ows_EmployeeID"),
courseID = (string)a.Attribute("ows_CourseID"),
title = (string)a.Attribute("ows_LinkTitle")
} into g
select new Dictionary<string, string>
{
{"employeeID", g.Key.employeeID },
{"courseID", g.Key.courseID },
{"title", g.Key.title}
} into f
select f).ToList();
select new Dictionary<string, string> {
{ "employeeID", ex.Key.title },
...
}
Using dot/fluent syntax, this is what I believe you want:
XElement xmlData = XElement.Parse(items.Xml);
List<Dictionary<string,string>> itemsNotSynched =
xmlData.Descendants(XName.Get("row", "#RowsetSchema"))
.Select(a => new
{
employeeID = (string)a.Attribute("ows_EmployeeID"),
courseID = (string)a.Attribute("ows_CourseID"),
title = (string)a.Attribute("ows_LinkTitle")
})
.Distinct()
.Select(a => new Dictionary<string, string>
{
{"employeeID", a.employeeID },
{"courseID", a.courseID },
{"title", a.title}
})
.ToList();
Distinct() accomplishes the same thing as grouping but only using the keys. As written, this Distinct() implementation is nearly identical to what you already had, but it may perform better and/or use less memory.