Flattening a Dictionary of strings - c#

I have this line of code:
Dictionary<string,string> alreadyThere = GetItFromFooMethod();
List<string> flatList = alreadyThere.Values.SelectMany(a => a).ToList();
But I get this compile error:
Cannot implicitly convert type 'System.Collections.Generic.List<char>' to 'System.Collections.Generic.List<string>'
Why does it think I need char? and how can I fix it?

I think you just want to get the Values like this:
List<string> flatList = alreadyThere.Values.ToList();
Since string is an IEnumerable<char>, SelectMany returns IEnumerable<char>. It thinks that you are trying to get each character separately into a list. But I don't think you want that..
Flattening can be useful only if you have a IEnumerable<IEnumerable<T>> for example if you would have a Dictionary<string, List<string>> then that code would work.But in your case the Values collection is already an IEnumereable<string>,so calling ToList should be enough...

Related

Error System.Collections.Generic.List`1[System.String] when itry String.Join on a list of result

I am getting the error System.Collections.Generic.List`1[System.String] when i try to use String.Join in a list of result.
For instance i have two list like this:
var list1= new List<string>{"string1","string2"};
var list2= new List<string>{"string1"};
Then i want to get a message with the string that doesn't appear on list2
var resultList1 = list1.Except(list2).ToList(); // this line get a list with "string2"
when i use String.Join i get the error System.Collections.Generic.List`1[System.String]. Also i tried resultList1.Cast<List>() instead resultList1 with same outcome.
var message = "List strings not found:\n\n"
+ String.Join(",", $"\n\n{resultList1}\n\n");
You need to use the string join like ths,
var message = "List strings not found:\n\n" + String.Join(",", resultList1);
You are using the system join on an enumerable array but when you use $"\n\n{result1}\n\n" string interpolation, you are basically joining a single string which doesn't work.
String.Join takes in a string (comma, newline or any string) that combines all elements from an array but when you give string instead of array or collection, it will give the error.
Lastly, Documentation should help explain more about the usage in depth.

object to string[]

I am working with some existing C# code. Essentially, I have a variable which is a List of objects.
Each of the objects, in turn is a string[n]. I know n, and the value is the same for all the objects in the list. What I need to know is how to loop over the list of objects and get, for each item, a
string[n]
I read your question as how to cast an object of compile time type Object to its run time type of string[]. You do that like so:
Object obj = ...;
string[] arr = (string[]) obj;
What about just casting the object to string[]?
string[] arr = (string[])listOfObjects[x];
It sounds like you want the Cast method:
foreach(string[] strings in listOfStringArrays.Cast<string[]>())
{
// ...
}
Use Enumerable.SelectMany. It projects each element of a sequence to an IEnumerable and flattens the resulting sequences into one sequence.
var resultantArray = myarray.SelectMany(x => x).ToArray();

Could not find an implementation of the query pattern Error

Given
var selectedItems = listBoxControl1.SelectedItems;
var selectedItemsList = (from i in selectedItems
select i).ToList();
I receive Error
Could not find an implementation of the query pattern for source type
'DevExpress.XtraEditors.BaseListBoxControl.SelectedItemCollection'.
'Select' not found. Consider explicitly specifying the type of the
range variable 'i'.
using system.LINQ Done
I can use foreach so it must implement IEnumerable. I prefer to use LINQ over foreach to gather each string, if possible.
I want to take the ToString() values for each SelectedItem in the list box control and stick them in a List<string>. How can I do it?
I can use foreach so it must implement IEnumerable.
That's not actually true, but it's irrelevant here. It does implement IEnumerable, but not IEnumerable<T> which is what LINQ works over.
What's actually in the list? If it's already strings, you could use:
var selectedItemsList = selectedItems.Cast<string>().ToList();
Or if it's "any objects" and you want to call ToString you can use:
var selectedItemsList = selectedItems.Cast<object>()
.Select(x => x.ToString())
.ToList();
Note that the call to Cast is why the error message suggested using an explicitly typed range variable - a query expression starting with from Foo foo in bar will be converted to bar.Cast<Foo>()...
For LINQ to work, you need an IEnumerable<T>, straight IEnumerable isn't enough. Try:
var selectedItems = listboxControl1.SelectedItems.Cast<T> //where T is the actual type of the item
Try just
var result = listBoxControl1.SelectedItems.Cast<MyItemType>().ToList();

C# - Populate a list using lambda expressions or LINQ

It's been a while since I've used lambda expressions or LINQ and am wondering how I would do the following (I know I can use a foreach loop, this is just out of curiosity) using both methods.
I have an array of string paths (does it make a difference if it's an array or list here?) from which I want to return a new list of just the filenames.
i.e. using a foreach loop it would be:
string[] paths = getPaths();
List<string> listToReturn = new List<string>();
foreach (string path in paths)
{
listToReturn.add(Path.GetFileName(path));
}
return listToReturn;
How would I do the same thing with both lambda and LINQ?
EDIT: In my case, I'm using the returned list as an ItemsSource for a ListBox (WPF) so I'm assuming it's going to need to be a list as opposed to an IEnumerable?
Your main tool would be the .Select() method.
string[] paths = getPaths();
var fileNames = paths.Select(p => Path.GetFileName(p));
does it make a difference if it's an array or list here?
No, an array also implements IEnumerable<T>
Note that this minimal approach involves deferred execution, meaning that fileNames is an IEnumerable<string> and only starts iterating over the source array when you get elements from it.
If you want a List (to be safe), use
string[] paths = getPaths();
var fileNames = paths.Select(p => Path.GetFileName(p)).ToList();
But when there are many files you might want to go the opposite direction (get the results interleaved, faster) by also using a deferred execution source:
var filePaths = Directory.EnumerateFiles(...); // requires Fx4
var fileNames = filePaths.Select(p => Path.GetFileName(p));
It depends on what you want to do next with fileNames.
I think by "LINQ" you really mean "a query expression" but:
// Query expression
var listToReturn = (from path in paths
select Path.GetFileName(path)).ToList();
// Extension methods and a lambda
var listToReturn = paths.Select(path => Path.GetFileName(path))
.ToList();
// Extension methods and a method group conversion
var listToReturn = paths.Select(Path.GetFileName)
.ToList();
Note how the last one works by constructing the projection delegate from a method group, like this:
Func<string, string> projection = Path.GetFileName;
var listToReturn = paths.Select(projection).ToList();
(Just in case that wasn't clear.)
Note that if you don't need to use this as a list - if you just want to iterate over it, in other words - you can drop the ToList() call from each of these approaches.
It's just:
var listToReturn = getPaths().Select(x => Path.GetFileName(x)).ToList();
As already stated in other answers, if you don't actually need a List<string> you can omit the ToList() and simply return IEnumerable<string> (for example if you just need to iterate it, IEnumerable<> is better because avoids the creation of an other list of strings)
Also, given that Select() method takes a delegate, and there's an implicit conversion between method groups and delegates having the same signature, you can skip the lambda and just do:
getPaths().Select(Path.GetFileName)
You could do it like this:
return getPaths().Select(Path.GetFileName);
listToReturn = paths.ToList().Select(p => Path.GetFileName(p));

C#: Union of two ICollections? (equivalent of Java's addAll())

I have two ICollections of which I would like to take the union. Currently, I'm doing this with a foreach loop, but that feels verbose and hideous. What is the C# equivalent of Java's addAll()?
Example of this problem:
ICollection<IDictionary<string, string>> result = new HashSet<IDictionary<string, string>>();
// ...
ICollection<IDictionary<string, string>> fromSubTree = GetAllTypeWithin(elementName, element);
foreach( IDictionary<string, string> dict in fromSubTree ) { // hacky
result.Add(dict);
}
// result is now the union of the two sets
You can use the Enumerable.Union extension method:
result = result.Union(fromSubTree).ToList();
Since result is declared ICollection<T>, you'll need the ToList() call to convert the resulting IEnumerable<T> into a List<T> (which implements ICollection<T>). If enumeration is acceptable, you could leave the ToList() call off, and get deferred execution (if desired).
AddRange() appends the source list to the end of another, and may suit your needs.
destList.AddRange(srcList);
LINQ's Enumerable.Union will work:

Categories

Resources