I'm doing this to look up for specific key inside the dictionary with the same row id_d i want to find and it really works great with keys that really exist, but it whatever throws me the exception when a key doesn't match the query criteria in the parameters value.
if(sentences.TryGetvalue(values = (from keys in sentences where keys.key.id_d == rows.id_d selesck keys.Key).First(), out listOf))
do you know how can i resolve this issue, i mean, just avoiding those null references from values and continuing without being stopped by the exception.
an example would be something like this:
if(sentences.TryGetValue(values = (from keys in sentences where keys.key.id_d == rows.id_d selesck keys.Key).First(), out listOf))
{
//do whatever
}
else
{
//if the 'value' query doesn't match the criteria, don't do anything
}
It's not clear why you're using a dictionary if the TKey isn't actually the key you're going to use to look up a value - you're missing out on the constant time lookup. I can only assume you're using it elsewhere.
If you want to find a value based on a key predicate, you can just select the value (rather than the key) and return FirstOrDefault - TryGetValue isn't required. This will return the default value (likely null, unless TValue is a value type) in the case that no match is found:
var result =
(from pair in sentences
where pair.Key.id_d == rows.id_d
select pair.Value).FirstOrDefault();
Though this might read better if you used method syntax throughout:
var result = sentences
.Where(x => x.Key == rows.id_d)
.Select(x => x.Value)
.FirstOrDefault();
Related
I create a multiple keys dictionary as (registrantsFields is enumerable type)
var registrantsRepository = registrantsFields.ToDictionary(c => Tuple.Create(c.RegistrantID, c.FieldID, c.DataID));
I use ContainsKey to search the dictionary as
if (registrantsRepository.ContainsKey(Tuple.Create(registrantId, fieldId, dataId)))
So far it works fine.
But I want to search the dictionary with only 2 keys, i.e. what dictionary contains for certain registrantId and fieldId, but with any dataId. In other word, I like to find all items like
var entries = registrantsRepository(Tuple.Create(registrantId, fieldId, *))
How should it be done (perhaps in Linq)? Thanks.
I'd just create a separate Lookup.
var registrantsByIdAndField = registrantsFields
.ToLookup(r => Tuple.Create(c.RegistrantID, c.FieldID));
Then you still get fast lookups with this:
var entries = registrantsByIdAndField[Tuple.Create(registrantId, fieldId)];
There's no wildcard search like that, but there is a way to ignore those fields that you're not interested in when you're doing your search.
Iterate through the collection of Keys, referencing the properties of your Tuple that you're interested in matching on. You can do this using LINQ's Any method.
if (registrantsRepository.Keys.Any(x => x.Item1 == registrantId && x.Item2 == fieldId)
{
}
All good answers here. Is ToLookup an option for you?
https://msdn.microsoft.com/en-us/library/bb549073(v=vs.100).aspx
Edit: just realized #StriplingWarrior beat me to this!
Just some details. Get Records is a variable where it contains the results of my stored procedure. Now, what I want to ask is what if I want to remove the group by function but I still want to get the key and items? Is there a way to do it?
var sortResCinema = GetRecords.Where(x => test2.branch == x.Bbranch && test.movieName == x.MovieName && x.MovieName != null)
.GroupBy(x => x.MovieName,
(key, elements) =>
new
{
Id = key,
Items = elements.ToList()
}).ToList();
There's no need for GroupBy here since you are looking for a specific movieName.
I guess you wanted something like this:
var sortResCinema = GetRecords.Where(x => test2.branch == x.Bbranch && test.movieName == x.MovieName).ToList();
You can replace the GroupBy with a Select. The Select statement can be used to alter the type of the results returned, which is what you appear to want to do. Should work with exactly the same syntax as the second parameter. So replace "GroupBy" with "Select" and remove the first argument. The key and elements properties that are being used in the GroupBy statement are internal to that function so you'd need to work out what function you want to replace these by, for instance the key might be x.MovieName.
I need do a filter that request data with a parameter included in a list.
if (filter.Sc.Count > 0)
socios.Where(s => filter.Sc.Contains(s.ScID));
I try on this way but this not work, I tried also...
socios.Where( s => filter.Sc.All(f => f == s.ScID));
How I can do a filter like this?
socios.Where(s => filter.Sc.Contains(s.ScID));
returns a filtered query. It does not modify the query. You are ignoring the returned value. You need something like:
socios = socios.Where(s => filter.Sc.Contains(s.ScID));
but depending on the type of socios the exact syntax may be different.
In addition to needing to use the return value of your LINQ .Where(), you have a potential logic error in your second statement. The equivalent logic for a .Contains() is checking if Any of the elements pass the match criteria. In your case, the second statement would be
var filteredSocios = socios.Where( s => filter.Sc.Any(f => f == s.ScID));
Of course if you can compare object-to-object directly, the .Contains() is still adequate as long as you remember to use the return value.
I have an interface method whose signature is as follows:
void SetValues(IDictionary<string, object> the_values);
I have a client class that uses that method. I want The unit test for that class to verify that, in a particular case, a specific key and value pair are passed in. Right now, if I want to express that I'm expecting the SetValues method to be called with the single key-value pair { "Date", DateTime(1972,1,2) } I write the following:
item.Expect(i => i.SetValues(
Arg<IDictionary<string, object>>.Matches(
(items) => (items.Count() == 1 &&
items.First().Key == "Date" &&
(DateTime) items.First().Value == new DateTime(1972,1,2))));
The expectation seems to work, but my does that look ugly. Is there a better way to express expectations about the contents of a collection being passed in as a parameter?
Most likely no. I agree this is border line ugly. But what's even more important, it produces undecipherable exception message, like this:
IInterface.SetValues(items => items.Count() == 1 &&
items.First().Key == "Date" &&
(DateTime) items.First().Value == new DateTime(1972,1,2)); Expected #1, Actual #0.
Yeah, you'll know it failed. Not very useful information in 2 weeks time. Truth to be told, when this happens you'll most likely have to debug it to get to know what's going on. Instead, I suggest doing this:
item.Expect(i => i.SetValues(Arg<IDictionary<string, object>>.Is.Anything))
.WhenCalled(invocation =>
{
var items = invocation.Arguments
.OfType<IDictionary<string, object>>()
.First();
Assert.That(items.Count(), Is.EqualTo(1));
Assert.That(items.First().Key, Is.EqualTo("Date");
// ...
});
Or, putting verification into it's own method altogether:
item.Expect(i => i.SetValues(IsCalledWithCorrectPair()));
// ...
private IDictionary<string, object> IsCalledWithCorrectPair()
{
return Arg<IDictionary<string, object>>.Matches(items =>
{
Assert.That(items.Count(), Is.EqualTo(1));
Assert.That(items.First().Key, Is.EqualTo("Date");
// ...
return true;
});
}
For small fixed number of expecte item in a dictionary I think simple check for Count and particular entries is expressive enough. Test will fail if values are wrong...
items.Count() == 1 && items["Date"]== new DateTime(1972,1,2);
You can also use collection comparisons as covered in Comparing two collections for equality irrespective of the order of items in them.
Is there a way I can do something like this with Lambda expressions?
responses.Add(sr).Where(v.Responses.TryGetValue(v.responseType, out sr));
I want to use lambda expressions or a ternary operator instead of a typical if expression.
NB:
responses is a List<string> type.
v.Responses is a Dictionary of <enum ResponseType, string>
v is some object
sr is a string.
What you want to do is:
string sr;
if (v.Responses.TryGetValue(v.responseType, out sr))
responses.Add(sr);
There is no way to ease the syntax and get the same performance.
But you could do:
responses.AddRange( v.Responses.Where( p => p.Key == v.responseType )
.Select( p => p.Value ) );
You may want to think about what the last one is doing, because it is kind of stupid...
EDIT: the reason why it is stupid is because the last expression translates into:
foreach(var pair in v.Responses)
{
if (pair.Key == v.responseType)
responses.Add(pair.Value);
}
So if your ResponseType enumeration had 6 million entries, the program would iterate over the entire set of keys to find the correct entry. In your case, since you already know the key, you should use v.Responses[key] as it is extremely fast (see in which cases dictionaries must be use).
LINQ is not supposed to modify collections.
Couldn't you simply do something like this:
string sr;
if(v.Responses.TryGetValue(v.responseType, out sr))
responses.Add(sr);
If I understand your question correctly, this might do what you're looking for.
Based on your example code, I'm assuming that your object "v" contains a field named "responseType" of type RepsonseType.
var responses = v.Responses
.Where(r => r.Key == v.responseType)
.Select(r => r.Value)
.ToList();