I have a list that contains roleids and a dictionary that has database of roleids and menus accessible to that roleid.
Suppose a user has role 1,2,3 then how do I retrieve the distinct menus he can access from a dictionary?
List<int> roleids = new List<int>();
roleids.Add(1);
roleids.Add(2);
roleids.Add(3);
Dictionary<int, List<String>> Links = new Dictionary<int, List<string>>
{
{ 1, new List<String> { "Home", "About Us", "Logout", "Help" } },
{ 2, new List<String> { "Home", "Products", "Logout", "Help" } },
{ 3, new List<String> { "Home", "Customers", "Users", "Help" } }
};
I want to create a new list that contains menus accessible to user based on values in List roleids
If you do your initial select across the roleids list - you can leverage the fast-lookup nature of the dictionary
var menuItems = roleids
.Select(id => Links[id])
.SelectMany(roles => roles)
.Distinct();
Try this:
var distinct = Links
.Where(i => roleids.Contains(i.Key))
.SelectMany(i => i.Value).Distinct()
.ToList();
Retrieve at first Links where role id in user's roleids, then select from this subset the values and avoid duplicates with distinct:
var menus = Links.Where(l => roleids.Contains(l.key))
.SelectMany(k => k.Value)
.Distinct();
use this algorithm
public static List<string> GetMenuItems(List<int> userRoles)
{
var roleids = new List<int>();
roleids.Add(1);
roleids.Add(2);
roleids.Add(3);
var Links = new Dictionary<int, List<string>>()
{
{1,new List<String> {"Home","About Us","Logout","Help"}},
{2,new List<String>{"Home","Products","Logout","Help"}},
{3,new List<String>{"Home","Customers","Users","Help"}}
};
var roleLinks = Links
.Where(item => userRoles.Contains(item.Key))
.SelectMany(item => item.Value)
.ToList()
.Distinct();
}
Related
I have a lambda expression to remove duplicate emails from to cc and bcc.
lstCCEmailAddress.Remove(lstCCEmailAddress.Where(t => t.Email.Contains(email.Email, StringComparison.OrdinalIgnoreCase)).FirstOrDefault());
but the thing is I want to remove all the duplicate emails just not FirstOrDefault.
which one should I replace FirstOrDefault with
How can I re-write the above query.
Thanks in advance.
To remove duplicates for all those fields (TO,CC,BCC),
first you need to run distinct on "To"
second run distinct on "cc" then remove any emails which does exists from "to".
third run distinct on "bcc" and remove any records which does exists from "to" and "cc" fields
[Fact]
public void TestUniqeEmails()
{
var listToEmail = new List<string> { "a#a.com", "b.com", "b.com" };
var listCCToEmail = new List<string> { "a#a.com", "b.com", "c.com" };
var listBCCToEmail = new List<string> { "a#a.com", "b.com", "c.com", "d.com" };
var uniqueToEmail = listToEmail.Distinct();
var uniqueCCEmail = listCCToEmail
.Where(e => !uniqueToEmail.Any(e.Contains))
.Distinct();
var uniqueBCCEmail = listBCCToEmail
.Where(e => !listToEmail.Any(e.Contains))
.Where(e => !uniqueCCEmail.Any(e.Contains))
.Distinct();
Assert.Equal(2, uniqueToEmail.ToList().Count);
Assert.Single(uniqueCCEmail.ToList());
Assert.Single(uniqueBCCEmail.ToList());
}
You can use the .Distinct() function Of Linq.
static void Main(string[] args)
{
List<string> mail = new List<string>() { "test#gmail", "blub#gmail", "test#gmail" };
var x = mail.Distinct();
foreach (var item in x)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
Result:
test#gmail
blub#gmail
For more information:
https://learn.microsoft.com/de-de/dotnet/api/system.linq.enumerable.distinct?view=net-5.0
You can group by and select group
var DistinctItems = lstCCEmailAddress.GroupBy(x => x. Email).Select(y => y.First());
I'm trying to create a dictionary where the keys will be the elements in a pre-existing List<string> and the values will be List<List<string>> like this:
List<string> newDictKeys = new List<string>(new []{"12323","432234","45345435"});
List<string> listVal1 = new List<string>(new []{"dfgdfg","asdfds","wertert"});
List<string> listVal2 = new List<string>(new []{"ZCxzcx","xcvbcvb","gfhjfgj"});
List<List<string>> dictVals = new List<List<string>>();
Dictionary<string,List<List<string>> dict = new Dictionary<string,List<List<string>>();
Is there any simple, elegant way to do this?
EDIT
Essentially this would be the mapping:
"12323" -> ["dfgdfg","ZCxzcx"]
"432234" -> ["asdfds","xcvbcvb"]
"45345435" -> ["wertert","gfhjfgj"]
Since You will have two lists stored for the same key why not to combine two lists together?
List<string> newDictKeys = new List<string>{ "12323", "432234", "45345435"};
List<string> t = new List<string> { "dfgdfg", "asdfds", "wertert" };
List<string> t2 = new List<string>{ "ZCxzcx", "xcvbcvb", "gfhjfgj" };
t.AddRange(t2);
Dictionary<string,List<string>> dict = newDictKeys.ToDictionary(key => key, key => t);
UPDATE
With the list of objects:
List<string> newDictKeys = new List<string> { "12323", "432234", "45345435" };
List<string> t = new List<string> { "dfgdfg", "asdfds", "wertert" };
List<string> t2 = new List<string> { "ZCxzcx", "xcvbcvb", "gfhjfgj" };
Dictionary<string, List<object>> dict = newDictKeys.ToDictionary(key => key, key => new List<object> {t, t2});
UPDATE 2
This should make a trick:
List<string> newDictKeys = new List<string> { "12323", "432234", "45345435" };
List<string> t = new List<string> { "dfgdfg", "asdfds", "wertert" };
List<string> t2 = new List<string> { "ZCxzcx", "xcvbcvb", "gfhjfgj" };
Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
foreach (var key in newDictKeys.Where(key => t.Count > 0 && t2.Count > 0))
{
dict.Add(key, new List<string> {t.FirstOrDefault(), t2.FirstOrDefault()});
t.RemoveAt(0);
t2.RemoveAt(0);
}
UPDATE 3
With Queue
List<string> newDictKeys = new List<string> { "12323", "432234", "45345435" };
Queue<string> t = new Queue<string> (new []{ "dfgdfg", "asdfds", "wertert" });
Queue<string> t2 = new Queue<string>(new[] { "ZCxzcx", "xcvbcvb", "gfhjfgj" });
Dictionary<string, List<string>> dict = newDictKeys
.Where(key => t.Count > 0 && t2.Count > 0)
.ToDictionary(key => key, key => new List<string> {t.Dequeue(), t2.Dequeue()});
Updated Answer based on question update
Ok, so you want the nth item from each value list as the values, which would look like this:
List<string> newDictKeys = new List<string>(new []{"12323","432234","45345435"});
List<string> listVal1 = new List<string>(new []{"dfgdfg","asdfds","wertert"});
List<string> listVal2 = new List<string>(new []{"ZCxzcx","xcvbcvb","gfhjfgj"});
List<List<string>> dictVals = new List<List<string>>();
dictVals.Add(listVal1);
dictVals.Add(listVal2);
Dictionary<string, List<string>> dict =
newDictKeys.Select((key, index) => new {key, index})
.ToDictionary(entry => entry.key,
entry => new List<string>(){dictVals[0][entry.index], dictVals[1][entry.index]});
Basically, it iterates through all the keys in newDictKeys, creates a temporary anonymous object with the key and the index of that key into the newDictKeys list (so {"12323", 0}, {"432234", 1}, ...). Then, it creates a Dictionary where the key is the value from newDictKeys and for the value it gets the values from each sub-list in dictValues at the same index location.
Or, a simplified version (directly access the listVal1 and listVal2 collections instead of dictVals:
Dictionary<string, List<string>> dict =
newDictKeys.Select((key, index) => new {key, index})
.ToDictionary(entry => entry.key,
entry => new List<string>(){listVal1[entry.index], listVal2[entry.index]});
Original Answer
If you want the same set of values for each entry in newDictKeys, you could map it like this:
List<string> newDictKeys = new List<string>(new []{"12323","432234","45345435"});
List<string> listVal1 = new List<string>(new []{"dfgdfg","asdfds","wertert"});
List<string> listVal2 = new List<string>(new []{"ZCxzcx","xcvbcvb","gfhjfgj"});
List<List<string>> dictVals = new List<List<string>>();
dictVals.Add(listVal1);
dictVals.Add(listVal2);
Dictionary<string, List<List<string>>> dict =
newDictKeys.ToDictionary(key => key, key => dictVals);
If you want a different set of values for each entry in newDictKeys, put the values into an array as well, so that they are in the same order as the keys, you could use .Select() to get the index of the key in the key list and then .ToDictionary() to map to the values you want, like this:
var valuesArray = new []{dictVals, dictVals2, ...};
Dictionary<string, List<List<string>>> dict =
newDictKeys.Select((key, index) => new {key, index})
.ToDictionary(entry => entry.key, entry => valuesArray[entry.index]);
The valuesArray could also be a list, as long as it's values can be retrieved by an indexer.
How can I convert the following lambda expression for running a SharePoint query in CSOM to accept an array of parameters:
Current working version:
var listItems = list.GetItems(query);
clientContext.Load(listItems,
items => items.Include(
item => item["Title"],
item => item.RoleAssignments
)
);
clientContext.Load(list, l => l.Id, l => l.DefaultDisplayFormUrl);
clientContext.ExecuteQuery();
How I would like it to work:
var fields = new List<string>()
{
"Title",
"ID",
"DocumentOrder",
"FileRef"
};
var listItems = list.GetItems(query);
clientContext.Load(listItems,
items => items.Include(
item => fields,
item => item.RoleAssignments
)
);
clientContext.Load(list, l => l.Id, l => l.DefaultDisplayFormUrl);
clientContext.ExecuteQuery();
This throws an error, is it possible to pass in a dynamic list?
Though not ideal, I have been able to achieve what I am attempting to do by calling Load several times in a loop:
var fieldNames = new List<string>()
{
"Title",
"ID",
"DocumentOrder",
"FileRef"
};
var listItems = list.GetItems(query);
foreach (var fieldName in fieldNames)
{
clientContext.Load(listItems,
items => items.Include(
item => item[fieldName]
)
);
}
clientContext.ExecuteQuery();
How can I use LINQ to select all the Company Name and Company ID from all the rows? I need something like this pseudo-code:
var typedQry = from b in allData.AsEnumerable()
where b.GetHeader("xxx") == "08/10/09 to 08/26/09"
select CompanyName, CompanyID, ...
The code below selects only one Company Name. Instead, I want Company Name from all the rows:
var typedQry3 = from b in allData.AsEnumerable()
select new { compname0 = b._rows[0][5]};
The data in _rows are Company Name (e.g., allData[0]._rows[0][5], allData[0]._rows[1][5],....), Company ID, and so forth.
However, Company Name, Company ID, and etc. are not defined in the DataProperty class. Their values are inserted into _rows from data files.
Any help is appreciated. Below is some code to help you understand my question.
List<DataProperty> allData = new List<DataProperty>();
The DataProperty class consists of
private readonly Dictionary<string, string> _headers = new Dictionary<string, string>();
private readonly List<string[]> _rows = new List<string[]>();
and these methods (among others):
public string[] GetDataRow(int rowNumber){return _rows[rowNumber];}
public void AddDataRow(string[] row){_rows.Add(row);}
according to your comment, if you need to the sum for each company you can try this:
var RowList1 = allData.SelectMany(u => u._rows.Select(t => new
{
CompanyName = t[5],
Amount = Convert.ToInt64(t[1]) + Convert.ToInt64(t[2])
}))
.Where(u => u.CompanyName == "XXX")
.OrderBy(u => u.CompanyName)
.ToList();
and if you need to sum of the all companies, you can try this:
var SumAmount = allData.SelectMany(u => u._rows.Select(t => new
{
CompanyName = t[5],
Amount = Convert.ToInt64(t[1]) + Convert.ToInt64(t[2])
}))
.Where(u => u.CompanyName == "XXX")
.DefaultIfEmpty()
.Sum(u => u.Amount);
you can write your own and customized query using these
you can use this to get all company names:
var AllCompanyNames = allData.SelectMany(u => u._rows.Select(t => t[5])).ToList();
and this, to get more property:
var Rows = allData.SelectMany(u =>
u._rows.Select(t => new
{
CompanyName = t[5],
Other1 = t[1],
Other2 = t[2]
}))
.ToList();
and this, if you need to check any condition:
var FilteredRows = allData.SelectMany(u =>
u._rows.Select(t => new
{
CompanyName = t[5],
Other1 = t[1],
Other2 = t[2]
}))
.Where(u => u.CompanyName == "XXX")
.ToList();
At first you can receive rows and then iterate through them.
This example may help you
var rows = (from DataRow dRow in dTable.Rows
select new {col1=dRow["dataColumn1"],col2=dRow["dataColumn2"]});
foreach (var row in distinctRows)
{
var value1=row.col1.ToString();
var value2=row.col2.ToString();
}
I have following file names in my files folder
1000_A.csv
1000_B.csv
1000_C.csv
1001_A.csv
1001_B.csv
files names starting with same ID needs to be added to a list and then the list needs to added to a dictionary with ID as key
For ex:
list x contains "1000_A.csv", "1000_B.csv", "1000_C.csv"
add this to a dictionary with ID 1000 as the key Please help.
You can use LINQ's GroupBy:
Dictionary<int, List<string>> idFilenames = fileList
.Select(fileName =>
{
string fnwoe = Path.GetFileNameWithoutExtension(fileName);
string idPart = fnwoe.Split('_').First();
int id;
int.TryParse(idPart, out id);
return new { fileName, id };
})
.GroupBy(x => x.id)
.ToDictionary(g => g.Key, g => g.Select(x => x.fileName).ToList());
var folder = GetFolder();
var files = new Dictionary<int, List<string>>();
foreach (var file in folders)
{
int id = Convert.ToInt32(file.Substring(0, file.IndexOf('_'));
if (files.Any(x => x.Key == id))
files[id].Add(file);
else
{
var newList = new List<string>();
newList.Add(file);
files.Add(id, newList);
}
}
var listOfFiles = ...; // assuming you can read the list of filenames
// into a string[] or IList<string>
var d = listOfFiles.GroupBy( f => f.Substring( 0, f.IndexOf( '_' ) ) )
.ToDictionary( g => g.Key, g => g );
e.g CSV the list of your csv files
Loop through you CSV list:
Dictionary<string, int> Dict = new Dictionary<string, int>();
List<string> files = new List<string>();
foreach (string path CSV)
{
if(!ContainsKey(path.Substring(0,3))
{
files.Add(path);
Dict.Add(path.Substring(0,3),files);
}
else
{
files.Add(path);
Dict[path.Substring(0,3)].Add(file);
}
}