If I have this ConcurrentDictionary:
public class User
{
public string Context { get; set; }
public bool Owner { get; set; }
}
protected static ConcurrentDictionary<User, string> OnlineUsers = new ConcurrentDictionary<User, string>();
Does anyone know how I would get the value of Owner if I already have the value of the Context? Basically I want to do a "find" using the Context. Thanks.
Does anything stop you from using standard Linq FirstOrDefault() method like so:
var item = OnlineUsers.FirstOrDefault(kvp => kvp.Key.Context == myContext);
How obout something like
var ou = OnlineUsers.First(x => x.Key.Context == "TADA");
It sounds like you need a Dictionary<string, User> which, when given the context as a string will tell you which User it corresponds to. If you are going to need to perform this lookup several times, and there isn't a problem using the additional memory, it may be worth creating such a dictionary.
If you are only going to be doing the search once or twice, or the mappings will be changing so often that you can't keep the dictionary up to date, then you can simply do a linear search on the dictionary using a foreach loop, or using a LINQ method such as First or Where, as demonstrated in other answers.
Here you go:
ConcurrentDictionary<User, string> dict = new ConcurrentDictionary<User, string>();
dict.TryAdd(new User() { Context = "a", Ownder = false }, "aa");
dict.TryAdd(new User() { Context = "b", Ownder = false }, "bb");
dict.TryAdd(new User() { Context = "c", Ownder = true }, "cc");
dict.TryAdd(new User() { Context = "d", Ownder = false }, "dd");
IEnumerable<User> list = dict.Keys.Where(p => p.Context == "a");
Related
I have a Dynamo table of US states and each state has a list of businesses. The structure is as follows:
{"Name": {S: "Ohio"},"Businesses":{"L": [ { M: {"Name":{"S":"McDonalds"}}, { M: {"Name":{"S":"IHOP"}} ] }
My goal is to write a function that can take a list of businesses and IF they don't exist already append them to the list of businesses, I have gotten this far:
public async Task UpdateStatesBusinessList(Buisness buisness)
{
var dynamoRequest = new UpdateItemRequest
{
Key = new Dictionary<string, AttributeValue>
{
{"Name", new AttributeValue{S = buisness.Name}}
},
ExpressionAttributeNames = new Dictionary<string, string>
{
{"#B", "Businesses" }
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{":B", new AttributeValue{L = business.Businesses}};
}
}
}
Public class Business
{
public string Name {get; set;}
}
We can pretend I have a hard coded list of businesses like:
BusinessList = new List<Business>
{
new Buisness {Name = "Chilis"}, new Buisness {Name = "BurgerKing"},etc...
}
I know I need to use an update expression with SET and use the if_not_exists() with list_append(). I need help constructing the request because my ExpressionAttributeValue is not correct... Any advise would be great, I have looked through all the AWS documentation and countless websites and have not been able to get it to work.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp5
{
class Validator
{
static void Main()
{
var metaValues = new List<Meta>
{
new Meta(4, 15, true),
new Meta(5, 20, false)
};
var requestDict = new Dictionary<int, List<int>>
{
{4, new List<int>{15,20} },// error not exist
{5, new List<int>{25} }, // error its false
{6, new List<int>{30} } // error not exist
};
var matchedIds = new List<int>();
if (metaValues.Any())
{
foreach (var ob in metaValues)
{
if (requestDict.ContainsKey(ob.Id))
{
matchedIds.Add(ob.Id);
var valuesDict = requestDict[ob.Id];
//here i cant get all the values and its Active of meta.Id
}
}
}
foreach (var key in requestDict.Keys)
{
if (!matchedIds.Contains(key))
Console.WriteLine("Invalid");
}
}
}
public class Meta
{
public int Id { get; private set; }
public int Value { get; private set; }
public bool IsActive { get; private set; }
public Meta(int id, int value, bool isActive)
{
Id = id;
Value = value;
IsActive = isActive;
}
}
}
iterating dictionary with object causing performance issue since everytime dictionary key has to be iterated in an list of object so i am trying to take object and lookup in dictionary on below condition
Invalid when meta.Id does not exist in dictionary key
Invalid when one of the meta.Value does not exist in dictionary values List
Inactive when meta.Id and meta.value match with dictionary but meta.isactive is false
I probably shouldn't bother answering since:
The code is quite messy
It does not compile
The question is very unclear
However, for some reason I feel like I understand a little what you're trying to do and wanted to provide some help.
First, let's NOT name a class with the same name as a built-in type (System.Object). Perhaps Item is generic enough? Also, you appear to instantiate instances of this class by calling a constructor that doesn't exist, so let's add that constructor as well:
public class Item
{
public int Id { get; }
public int Value { get; }
public bool IsActive { get; }
public Item(int id, int value, bool isActive)
{
Id = id;
Value = value;
IsActive = isActive;
}
}
Now we can create our list of Item objects by calling the constructor:
var items = new List<Item>
{
new Item(4, 15, true),
new Item(5, 20, false)
};
It also appears that you're creating a dictionary that contains a Key of type int that maps to Item.Id, and a Value of type List<int> that sort-of maps to Item.Value (though Item.Value is a single int). A problem in the code you posted is that you're trying to add two items with the same Key value of 4, which is not legal for a Dictionary - all the keys must be unique. To fix this, I'm using unique keys:
var requests = new Dictionary<int, List<int>>
{
{4, new List<int> {15}},
{5, new List<int> {20}},
{6, new List<int> {25}},
{7, new List<int> {30}}
};
Next it appears that you're trying to create a List<int> of numbers representing the Item.Id values that exist as dictionary keys. This can be done with a System.Linq extension method:
var matchedIds = items
.Where(item => requests.ContainsKey(item.Id))
.ToList();
And finally, it's not exactly clear what you want to do with this list, but it appears you want to do something if either an Item.Id does not exist in the dictionary, or the Item.Id exists but the Item.Value is not in the list, or the item does exist, but the Item.IsActive value is false, or some other combination of these properties.
Here's how to get those items:
var matchedIds = items
.Where(item => requests.ContainsKey(item.Id))
.ToList();
var matchedIdsAndValues = matchedIds
.Where(item => requests[item.Id].Contains(item.Value))
.ToList();
var matchedIdsMissingValue = matchedIds
.Where(item => !requests[item.Id].Contains(item.Value))
.ToList();
var unmatchedIds = items
.Where(item => !requests.ContainsKey(item.Id))
.ToList();
var matchedIdAndValueButNotActive = matchedIdsAndValues
.Where(item => !item.IsActive)
.ToList();
Hope this helps!
I was wondering if I could replace this foreach with LINQ queries somehow (if possible):
Online playpen: https://ideone.com/PQEytf
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
public static void Main()
{
// dummy inputs for test sake
var keys = new[] { "key1", "key2" };
var services = new Dictionary<string, Service>
{
{"key1", new Service {Components = new Dictionary<string, string> {{"comp1", "value1"}}}},
{"key2", new Service {Components = new Dictionary<string, string> {{"comp2", "value2"}}}}
};
var serviceComponents = GetServiceComponents(keys, services);
// do something with it
}
public static IEnumerable<ServiceComponent> GetServiceComponents(string[] keys, Dictionary<string, Service> services)
{
var serviceComponents = new List<ServiceComponent>();
// this is the foreach that I want to lose
foreach (
var key in
keys.Select(
name =>
services.FirstOrDefault(
x => x.Key.Equals(name))))
{
serviceComponents.AddRange(key.Value.Components.Select(component => new ServiceComponent
{
Name = key.Key,
Service = component.Key,
Value = component.Value,
}));
}
return serviceComponents.ToArray();
}
}
public class Service
{
public Dictionary<string, string> Components { get; set; }
}
public class ServiceComponent
{
public string Name { get; set; }
public string Service { get; set; }
public string Value { get; set; }
}
Yes, what you're looking for is SelectMany. That allows you to turn each item in the sequence into another sequence, and then flatten all of those sequences into a single sequence. (You're accomplishing the same thing, without the deferred execution, by putting all of the sequences into a list.)
return keys.SelectMany(name => services.FirstOrDefault(x => x.Key.Equals(name))
.Value.Components
.Select(component => new ServiceComponent
{
Name = name.Key,
Service = component.Key,
Value = component.Value,
}))
.ToArray();
Having said that, what this query is doing is taking each of your keys, finding the corresponding item in services using a linear search, and then mapping the result. Rather than doing a linear search using FirstOrDefault, you can use the dictionary's native ability to effectively and efficiently find values for each key:
return keys.SelectMany(key => services[key].Components
.Select(component => new ServiceComponent
{
Name = key,
Service = component.Key,
Value = component.Value,
}))
.ToArray();
To extend #Servy's example, I often find the LINQ expression syntax to be easier to read than the lambda SelectMany (it translates to the same thing). Here is his query using query expressions:
return from key in keys
from component in services[key].Components
select new ServiceComponent
{
Name = key,
Service = component.Key,
Value = component.Value,
}))
.ToArray();
What you need is SelectMany, however, by using FirstOrDefault you're opening yourself up to a NullReferenceException (as the default value for any reference type is null). If you intend to have a NullReferenceException thrown when an element of keys is not a key in services then you can use other answers which leverage SelectMany. However, is you do not intend a NullReferenceException, then you should use something like the following:
return services.Where(pair => keys.Contains(pair.Key))
.SelectMany(pair =>
pair.Value.Components
.Select(component => new ServiceComponent
{
Name = pair.Key,
Service = component.Key,
Value = component.Value
}))
.ToArray();
This statement removes all key-value pairs from services whose key is not in the keys array, then turns each element of each pair's Components into a new ServiceComponent object, with the SelectMany making a single flat list out of the new ServiceComponents.
I have a Dictionary<string, User>.
User is an object with the properties UID, UNIQUE KEY and more. My dictionary key is the UNIQUE KEY of the users.
Now, i want to get a User from my dictionary values by a UID and not the key, something like ContainsKey.. how its done with lambda expr or linq? is there a good solution for that?
Here's a working sample:
using System;
using System.Collections.Generic;
using System.Linq;
internal class User
{
public string ID { get; set; }
public string Name { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
Dictionary<string, User> dic = new Dictionary<string, User>();
dic.Add("1", new User { ID = "id1", Name = "name1" });
dic.Add("2", new User { ID = "id2", Name = "name2" });
dic.Add("3", new User { ID = "id3", Name = "name3" });
User user = dic.Where(z => z.Value.ID == "id2").FirstOrDefault().Value;
Console.ReadKey();
}
}
return dict.Single(x => x.Value.UID == target);
Of course, you might find that your design is questionable if it involves continually doing linear searches across a Dictionary.
Of course you'll loose the benefit of having a dictionary, but you can do someting like:
var user = dict.Values.FirstOrDefault(k=>k.UID==xxxx);
This should get the user for the UID from the dictionary:
public User GetUserForUid(Dictionary<string, User> dictionary, int uid)
{
return dictionary.Values.FirstOrDefault(u => u.UID == uid);
}
I want know to make a query using linq, between a collection of objects
and a collection of values. In the sample code below, I make the question about it.
class USER
{
public string Name { get; set; }
}
public class MyClass
{
public MyClass()
{
List<USER> listUser = new List<USER>();
listUser.Add(new USER { Name = "A" });
listUser.Add(new USER { Name = "B" });
listUser.Add(new USER { Name = "C" });
listUser.Add(new USER { Name = "D" });
string[] arrayNames = { "A", "B" };
}
}
Using Linq how can I get all USER in listUser with them Name equals to the arrayNames values.?
The expected results wold be
//listUser[0] --> User with Name == "A"
//listUser[1] --> User with Name == "B"
Thanks in advance.
HashSet<string> names = new HashSet<string>(new string[]{ "A", "B" });
var selectedUsers = listUser.Where(user => names.Contains(user.Name));
The hashset is optional and overkill if you have only a few users but it guarantees optimal lookup performance if you have a lot of users.
listUser.Where(u => arrayNames.Contains(u.Name)).ToList();
This should so what you want, tried it in a console app. Worked a treat
var query = listUser.Where(i => arrayNames.Contains(i.Name));
foreach (var item in query)
{
Console.WriteLine(item.Name);
}
Console.ReadKey();
The key part is the arrayNames.Contains(i.Name) as this is inverse to intuition in that you specify the IEnumerable and then the linq parameter inside the contains method.
listUser = (from u in listUser where arrayNames.Contains(u.Name) select u).ToList();