Intersperse a List<> [duplicate] - c#

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Extension method for Enumerable.Intersperse?
I have a List<string> like this:
"foo", "bar", "cat"
I want it to look like this:
"foo", "-", "bar", "-", "cat"
Is there a C# method that does that?

You can make an extension that returns an IEnumerable<T> with interspersed items:
public static class ListExtensions {
public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> items, T separator) {
bool first = true;
foreach (T item in items) {
if (first) {
first = false;
} else {
yield return separator;
}
yield return item;
}
}
}
The advantage of this is that you don't have to clutter your list with the extra items, you can just use it as it is returned:
List<string> words = new List<string>() { "foo", "bar", "cat" };
foreach (string s in words.Intersperse("-")) {
Console.WriteLine(s);
}
You can of course get the result as a list if you need that:
words = words.Intersperse("-").ToList();

Here is an implementation out of my personal toolbox. It's more general than what you require.
For your particular example, you would write
var list = new List<string> { "foo", "bar", "cat" };
var result = list.InterleaveWith(Enumerable.Repeat("-", list.Count - 1));
See it in action.

public List<string> GetNewList(List<string> list, string s)
{
var result = new List<string>();
foreach (var l in list)
{
result.Add(l);
result.Add(s);
}
result.RemoveAt(result.Count - 1);
return result;
}
you can use this method to get you list
var result = GetNewList(str,"-");

Hah! I've just written something for just this purpose!
public static IEnumerable<T> Interleave<T>(params IEnumerable<T>[] arrays)
{
var enumerators = arrays.Select(array => array.GetEnumerator()).ToArray();
var finished = true;
do
{
finished = true;
foreach (var enumerator in enumerators)
{
if (enumerator.MoveNext())
{
yield return enumerator.Current;
finished = false;
}
}
} while (finished == false);
}
This will interleave the specified enumerables in the order you choose.
Then you just fill an enumerable with dashes and interleave that with the original array. It can do more complex things as well.

A while ago I wrote an extension method for this kind of thing:
public static IEnumerable<T>
Join<T>(this IEnumerable<T> src, Func<T> separatorFactory)
{
var srcArr = src.ToArray();
for (int i = 0; i < srcArr.Length; i++)
{
yield return srcArr[i];
if(i<srcArr.Length-1)
{
yield return separatorFactory();
}
}
}
You can use it as follows:
myList.Join(() => "-").ToList()

EDIT:
As pointed out, my previous code results to a string not an array of strings. So here's my edited code:
var list = new List<string> { "foo", "bar", "cat" };
var result = string.Join("-", list.Select(x => x.ToString()).ToArray());
string pattern = "(-)";
string[] test = Regex.Split(result, pattern);
foreach(var str in test)
Console.WriteLine(str);
Retained old code for comparison purposes:
var list = new List<string> { "foo", "bar", "cat" };
var result = string.Join("-", list.Select(x => x.ToString()).ToArray());
Console.WriteLine(result); // prints "foo-bar-cat
Refer to this post. Cheers!

Yes, its a custom method you would write:
List<string> AddDashesToList(List<string> list)
{
if(list.Count > 1)
{
var newList = new List<string>();
foreach(item in list)
{
newList.Add(item);
newList.Add("-");
}
newList.RemoveAt(newList.Count-1);
return newList;
}
else
{
return list;
}
}

Related

C# How to Compare List<string[]> item to the next?

I have a List<string[]>, and I would like to compare the first array from the list to the next, then print the parts that are equal in both string arrays.
For instance:
public static void Main()
{
List<string[]> list = new List<string[]>();
string[] a = {"some", "random", "string"};
string[] b = {"some", "other", "random", "string"};
list.Add(a);
list.Add(b);
string[] difference = Compare(list);
}
public static string[] Compare (List<string[]> A)
{
//do something here
}
The end goal is to loop it to compare each string array to every other string array in the list.
Thanks in advance.
1. Find intersections of pairs of arrays in the list
private static IEnumerable<(string,string[])> Compare(List<(string Name,string[] Words)> lists)
{
for(int i = 0; i < lists.Count - 1; i++) {
var a = lists[i];
var b = lists[i + 1];
yield return ($"{a.Name}<->{b.Name}", a.Words.Intersect(b.Words).ToArray());
}
}
Test
Code
List<(string, string[])> list = new List<(string, string[])>();
string[] a = {"some", "random", "string"};
string[] b = {"some", "other", "random", "string"};
string[] c = {"some", "other2", "random", "string2"};
list.Add(("a", a));
list.Add(("b", b));
list.Add(("c", c));
foreach( var pair in Compare(list) )
Console.WriteLine($"{pair.Item1}: {string.Join(", ", pair.Item2)}");
Output
// .NETCoreApp,Version=v3.0
a<->b: some, random, string
b<->c: some, random
2. Find words in all arrays
private static string[] InAll(List<string[]> lists)
{
var inAll = new List<string>();
foreach(var list in lists ) {
foreach(var word in list) {
if(lists.All(l => l.Contains(word))) {
inAll.Add(word);
}
}
}
return inAll.Distinct().ToArray();
}
Test
Code
public static void Main(string[] args)
{
List<string[]> list = new List<string[]>();
string[] a = {"some", "random", "string"};
string[] b = {"some", "other", "random", "string"};
string[] c = {"some", "other2", "random", "string2"};
list.Add(a);
list.Add(b);
list.Add(c);
foreach( var inAll in InAll(list) ) Console.WriteLine(inAll);
}
Output
// .NETCoreApp,Version=v3.0
some
random
Let's implement (in general case) it with a help of Linq:
using System.Linq;
...
private static IEnumerable<T[]> Differences<T>(IEnumerable<IEnumerable<T>> source,
IEqualityComparer<T> comparer = null) {
if (null == source)
throw new ArgumentNullException(nameof(source));
if (null == comparer)
comparer = EqualityComparer<T>.Default;
if (null == comparer)
throw new ArgumentNullException(nameof(comparer),
$"No default comparer for {typeof(T).Name}");
Dictionary<T, int> prior = null;
foreach (var line in source) {
Dictionary<T, int> current = line
.GroupBy(item => item, comparer)
.ToDictionary(chunk => chunk.Key, chunk => chunk.Count(), comparer);
if (null != prior)
yield return current
.Where(item => prior.ContainsKey(item.Key))
.SelectMany(item => Enumerable
.Repeat(item.Key, Math.Min(item.Value, prior[item.Key])))
.ToArray();
prior = current;
}
}
Demo:
List<string[]> list = new List<string[]>() {
new [] { "some", "random", "string" },
new [] { "some", "other", "random", "string" },
new [] { "some", "some", "some" },
new [] { "some", "some", "other" },
new [] { "some", "other", "some" },
};
string demo = string.Join(Environment.NewLine, Differences(list)
.Select(line => string.Join(", ", line)));
Console.Write(demo);
Outcome:
some, random, string // 1st and 2nd strings
some // 2nd and 3d strings
some, some // 3d and 4th strings
some, some, other // 4th and 5th strings
If you want the 1st line only, add .FirstOrDefault():
string demo = Differences(list)
.Select(line => string.Join(", ", line))
.FirstOrDefault();
Console.Write(demo);
Outcome:
some, random, string
Finally, if you want to intersect all items (common items within all lines):
private static IEnumerable<T> IntersectAll<T>(IEnumerable<IEnumerable<T>> source,
IEqualityComparer<T> comparer = null) {
if (null == source)
throw new ArgumentNullException(nameof(source));
if (null == comparer)
comparer = EqualityComparer<T>.Default;
if (null == comparer)
throw new ArgumentNullException(nameof(comparer),
$"No default comparer for {typeof(T).Name}");
Dictionary<T, int> prior = null;
foreach (var line in source) {
Dictionary<T, int> current = line
.GroupBy(item => item, comparer)
.ToDictionary(chunk => chunk.Key, chunk => chunk.Count(), comparer);
if (null != prior)
prior = current
.Where(item => prior.ContainsKey(item.Key))
.ToDictionary(item => item.Key, item => Math.Min(item.Value, prior[item.Key]));
else
prior = current;
}
return (prior ?? new Dictionary<T, int>())
.SelectMany(item => Enumerable.Repeat(item.Key, item.Value));
}
For an arbitrary amount of lists to be compared you could write something like this:
public static string[] Compare (List<string[]> lists)
{
var temp = lists.First().ToList();
foreach(var l in lists)
{
temp = temp.Intersect(l).ToList();
}
return temp.ToArray();
}
This would result in
some
random
string
Of course you would add error handling in case of an empty list and so on...
public static string[] Compare(List<string[]> A)
{
string result = string.Empty;
foreach(string s in A[0])
{
if(A[1].Contains(s))
{
if(result==string.Empty)
{
result += s;
}
else
{
result += "," + s;
}
}
}
return result.Split(',');
}
It seems like you simply need the intersection of all the arrays:
private static string[] GetCommonElements(List<string[]> list)
{
if (!list.Any())
{
return Array.Empty<string>();
}
IEnumerable<string> result = list[0];
foreach (string[] collection in list.Skip(1))
{
result = result.Intersect(collection);
}
return result.ToArray();
}
Personally, I tried to solve the problem using linq, and I hope the code below can answer to your question .
Result :
public static IEnumerable<string> Compare(List<string[]> items)
{
var liste = new List<string>() ;
AddingElements(items, liste);
return liste.Distinct();
}
private static void AddingElements(List<string[]> items, List<string> liste)
{
items.Skip(1).ToList().ForEach((e) =>
{
liste.AddRange(e.Difference(items.First()));
});
}
public static string[] Difference(this string[] sourceArray, string[] stringArray)
{
return sourceArray.Where(e => stringArray.Contains(e))
.ToArray();
}

How to compare the contents of two arrays and returning the index of the duplicated file?

I've made a method that compares the files within two file directories and it returns if there are files that are duplicated in the form of a bool. However, would actually want it to return the files name or the index of the file in its array so I can then delete the file so their are no complications when moving files into one directory. I've tried to cast the "==" compare statement to a string hoping it would give the files name but I forgot since its a boolean operation it will only return true or false.
static public string ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
string NoDuplicateMods = "There are no duplicate mods";
foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
{
foreach (var ModInModsDirectory in SimsModsDirectory)
{
if (ModInDownloadDirectory == ModInModsDirectory)
{
string DuplicateMod = (ModInDownloadDirectory == ModInModsDirectory).ToString();
return DuplicateMod;
}
else
{
return NoDuplicateMods;
}
}
}
return NoDuplicateMods;
}
You can get the indexes of the matching strings with something like this
var result = SimsModDownloadDirectory.Select((x, i) =>
{return (SimsModsDirectory.Contains(x) ? i :-1);})
.Where(x => x != -1);
foreach(int index in result)
Console.WriteLine(index);
The idea is the following:
Enumerate with Select all the strings (x) in the first list with the overload that gives us also the index of the enumerated string (i), if the enumerated string is contained in the second list return its index otherwise return -1. Finally take with Where only the not -1 values extracted by the Select
Of course returning only the names of the duplicates is a lot more simple
var result = SimsModDownloadDirectory.Intersect(SimsModsDirectory);
foreach(string name in result)
Console.WriteLine(name);
These approaches are based on the exact match in case between the two strings to compare. So a string "Steve" will not match a string "steve".
If your requirements are to ignore case in the comparison then you could change to
var result = SimsModDownloadDirectory.Select((x, i) =>
{
return (SimsModsDirectory.Contains(x,
StringComparer.CurrentCultureIgnoreCase) ? i :-1);
}).Where(x => x != -1);
or to
var result = SimsModDownloadDirectory.Intersect(SimsModsDirectory,
StringComparer.CurrentCultureIgnoreCase);
The else in your code is the issue.
Sample code (untested)
static public string ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
string NoDuplicateMods = "There are no duplicate mods";
foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
{
foreach (var ModInModsDirectory in SimsModsDirectory)
{
if (ModInDownloadDirectory == ModInModsDirectory)
{
return ModInModsDirectory;
}
}
}
return NoDuplicateMods;
}
The above only returns the first duplicate. For all duplicates, you have to maintain a list and return that at the end
static public List<string> ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
var duplicateDirs = new List<string>();
foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
{
foreach (var ModInModsDirectory in SimsModsDirectory)
{
if (ModInDownloadDirectory == ModInModsDirectory)
{
duplicateDirs.Add(ModInModsDirectory);
}
}
}
return duplicateDirs;
}
I don't exactly know what are you trying to achieve. Your code does not tell us what should the return value be. If you want to tell the caller that "There is/isn't duplicate file names", you can easily return bool. If you want to return the "duplicate file names", you should return string[] or FileInfo[] or IReadOnlyCollection<string> or something similar. The advantage of returning a collection or array, is that the caller can easily see that if there is/isn't any duplicates, by checking the Length/Count of the returned value.
Using nested for loops, has a poor performance of O(n*m). Using a HashSet or LINQ's Intersect method, you can easily achieve the goal in O(n+m):
public static IReadOnlyList<string> FindDuplicateModFiles(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
var set = new HashSet<string>(SimsModDownloadDirectory);
var result = new List<string>();
foreach (string file in SimsModsDirectory)
{
if (set.Contains(file))
result.Add(file);
}
return result.AsReadOnly();
}
Or using LINQ:
public static IEnumerable<string> FindDuplicateModFiles2(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
return SimsModDownloadDirectory.Intersect(SimsModsDirectory);
}
If you want to remove the duplicates from the first collection, the best options is the LINQ's Except method:
public static IEnumerable<string> GetNonDuplicatesInFirst(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
return SimsModDownloadDirectory.Except(SimsModsDirectory);
}
static public IEnumerable<string> ModFileDupilcate(string[] SimsModDownloadDirectory,
string[] SimsModsDirectory)
{
var result = SimsModDownloadDirectory.Select((x, i) =>
SimsModsDirectory.Contains(x) ? x : string.Empty).
Where(x => !string.IsNullOrEmpty(x));
return result;
}
Call method like :
var resultOfDublicateFiles = ModFileDupilcate(SimsModDownloadDirectory,SimsModsDirectory);
Or
public static bool ModFileDupilcate(string[] SimsModDownloadDirectory,
List<string> SimsModsDirectory,out List<string> dublicatedFiles)
{
dublicatedFiles = new List<string>();
foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
{
foreach (var ModInModsDirectory in SimsModsDirectory)
{
if (ModInDownloadDirectory == ModInModsDirectory)
{
dublicatedFiles.Add(ModInModsDirectory);
}
}
}
return dublicatedFiles.Count > 0;
}
Call method like :
List<string> dublicatedFiles;
bool hasDublicatedFiles= ModFileDupilcate(new string["a","b","c"],new string["b","c","d","f"],out dublicatedFiles);

How do you iterate through a mixed List<t> and print contents to console in C#?

I have a List<object> which contains strings and even additional lists.
List<object> NewArray = new List<object>();
so basically the list contains a mixture....
As a sanity check, I want to print out the contents to the console. I start by iterating through and test to see whether the element is a list. If it isn't then it will be a string and can be printed to the console. If it is a list, I want to iterate through and print the string contents to the console but with a tab to indent it.
I have this so far:
for (int outer = 0; outer < NewArray.Count; outer++)
{
var innerList = NewArray[outer];
if (innerList.GetType().IsGenericType && innerList.GetType().GetGenericTypeDefinition() == typeof(List<>))
{
for (int inner = 0; inner < innerList.Count; inner++)
{
//print string
}
}
else
{
//print string
}
}
I didn't want to use a foreach loop as I'm not sure the order of the list would be guaranteed and will be in the future adding a increment number (which can be provided by the inner and outer variables).
The issue I am getting is an error here:
inner < innerList.Count
which is:
Operator '<' cannot be applied to operands of type 'int' and 'method group'
What do I need to do to overcome this? I'm not sure it is the most efficient way of achieving the end result but....
static void Main()
{
var randomCrap = new List<Object>
{
1, "two",
new List<object> { 3, 4 },
5, 6,
new List<object> {
new List<object> { 7, 8, "nine" },
},
};
randomCrap.PrintAll();
}
Output:
1
two
3
4
5
6
7
8
nine
Using this:
public static class Extensions
{
public static void PrintAll(this Object root)
{
foreach (var x in root.SelectAll())
{
Console.WriteLine(x);
}
}
public static IEnumerable<Object> SelectAll(this object o)
{
// Thank you, eocron
if (o is String)
{
yield return o;
}
else if (o is IEnumerable)
{
var e = o as IEnumerable;
foreach (var child in e)
{
foreach (var child2 in child.SelectAll())
yield return child2;
}
}
else
{
yield return o;
}
}
}
If you know your object is a List<> of some generic type, you could always cast to IList and loop through it that way.
To paraphrase your code:
if (innerList.GetType().IsGenericType && innerList.GetType().GetGenericTypeDefinition() == typeof(List<>))
{
var list = (IList)innerList;
for (int inner = 0; inner < list.Count; inner++)
{
Console.WriteLine(list[inner].ToString());
//print string
}
}
But in reality, you should be doing what itsme86 said, and making strong types with an overriden ToString() or Display() method.
Here is more simplistic way of doing what you want:
public static void DeepPrint(object obj, int recursionLevel)
{
if(obj == null)
{
//print null
return;
}
var str = obj as string;
if(str != null)
{
//print str
return;
}
var enumer = obj as IEnumerable;
if(enumer != null)
{
foreach(var e in enumer)
{
DeepPrint(e, recursionLevel+1);
}
return;
}
//print obj.ToString();
}
Then call it like this on whatever you desire:
DeepPrint(myObjectOrList, 0);
PS
For those who say about "random crap" - embrace the string.Format(...), embrace serialization in general, embrace WCF and dynamic, and etc. There is many random things in this world, what doesn't really need strong typing. In fact it will just become "crap" if you provide strong typing to some common used functions.
One way you could do it is to check if the object implements ICollection, and if so, iterate over the contents. I created a recursive method to handle cases where a collection contained other collections, which includes an indentAmount argument, so that nested collections are indented by a tab each time they're encountered:
public static void PrintItem(object item, int indentAmount = 0)
{
var indent = new string('\t', indentAmount);
if (item == null) Console.WriteLine($"{indent}<null>");
if (item is ICollection)
{
var innerItems = item as IEnumerable;
Console.WriteLine($"{indent}Collection type encountered:");
indentAmount++;
foreach (var innerItem in innerItems)
{
PrintItem(innerItem, indentAmount);
}
}
else
{
Console.WriteLine($"{indent}{item}");
}
}
Usage
private static void Main()
{
var items = new List<object>
{
"first",
2,
new List<string> {"listFirst", "listSecond"},
new[] {"arrayFirst", "arraySecond"},
new ArrayList {"arrayListFirst", "arrayListSecond"},
"third",
new List<List<string>>
{
new List<string> {"nestedList1First", "nestedList1Second"},
new List<string> {"nestedList2First", "nestedList2Second"}
},
4f,
new object[] {5d, "six", new List<object>{"seven", 8} },
9,
"ten"
};
PrintItem(items);
Console.WriteLine("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Output

Trying to compare two lists c# - Should work?

I have a method that looks like this:
GetDrawing(Dictionary<string, List<string>> AllDrawings, Dictionary<string, bool> ImportData, string[] ItemsToCompare)
Firstly, the method creates a new List<string> with all the items from ImportData<string, bool> that have the value true and can be found in string[] ItemsToCompare
Secondly, I would like to compare the new List<string> with the List from AllDrawings<string, List<string>>. The method is in the end supposed to return a string with the key from AllDrawings<string>, List<String>> where the two lists match.
I have now spent a lot of hours trying to figure this out myself and also tried every answer I could find to similar questions here on Stackoverflow but with no luck.
Below is the full code for my method. As mentioned above I've tried a lot of different methods to compare the lists but the one following below is the latest try.
public static string GetDrawing(Dictionary<string, List<string>> AllDrawings, Dictionary<string, bool> ImportData, string[] ItemsToCompare)
{
string FinalDrawing = "";
try
{
List<string> AllCorrect = new List<string>();
foreach (var item in ImportData)
{
if (item.Value == true && ItemsToCompare.Contains(item.Key))
AllCorrect.Add(item.Key);
}
AllCorrect.Sort();
foreach (var DrawItem in AllDrawings)
{
DrawItem.Value.Sort();
var match = AllCorrect.SequenceEqual(DrawItem.Value);
if (match == true)
{
FinalDrawing = DrawItem.Key;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return FinalDrawing;
}
My problem is that the return value from var match = AllCorrect.SequenceEqual(DrawItem.Value); is false and therefore the FinalDrawing is never set.
All answers are very appreciated.
Thanks in advance!
Ok.. I already said that in comments, but just to make sure that you don't get yelled at too much for not-using-linq and such:
your program seems correct up to the point you told us.
Here's a simple test. I provided some stub data that cover all things that you seem to check:
only true things from importedata
only things that are listed in itemstocompare
input lists are not sorted
-> http://rextester.com/HAE73942
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
public class Program
{
// your original function, nothing changed
public static string GetDrawing(Dictionary<string, List<string>> AllDrawings, Dictionary<string, bool> ImportData, string[] ItemsToCompare)
{
string FinalDrawing = "";
try
{
List<string> AllCorrect = new List<string>();
foreach (var item in ImportData)
{
if (item.Value == true && ItemsToCompare.Contains(item.Key))
AllCorrect.Add(item.Key);
}
AllCorrect.Sort();
foreach (var DrawItem in AllDrawings)
{
DrawItem.Value.Sort();
var match = AllCorrect.SequenceEqual(DrawItem.Value);
if (match == true)
{
FinalDrawing = DrawItem.Key;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return FinalDrawing;
}
public static void Main(string[] args)
{
var allDrawings = new Dictionary<string, List<string>>();
allDrawings.Add("aaa", new List<string>{ "a03", "a01", "a02" }); // originally unsorted
allDrawings.Add("bbb", new List<string>{ "b03", "b01", "b02" }); // originally unsorted
allDrawings.Add("ccc", new List<string>{ "c03", "c01", "c02" }); // originally unsorted
var import = new Dictionary<string, bool>();
import.Add("b01", false); // falsey
import.Add("a05", true); // not in comparison
import.Add("a03", true);
import.Add("c01", false); // falsey
import.Add("a02", true);
import.Add("a04", true); // not in comparison
import.Add("a01", true);
var toCompare = new string[9];
toCompare[0]="a01"; toCompare[1]="a02"; toCompare[2]="a03";
toCompare[3]="b01"; toCompare[4]="b02"; toCompare[5]="b03";
toCompare[6]="c01"; toCompare[7]="c02"; toCompare[8]="c03";
var result = GetDrawing(allDrawings, import, toCompare);
Console.WriteLine("Result: " + result);
}
}
it works fine and prints aaa as it should.
This means that you had to have overlooked something in the input data. Maybe some strings are uppercase/lowercase? Maybe some strings have whitespaces inside and others not?
This code :
List<string> AllCorrect = new List<string>();
foreach (var item in ImportData)
{
if (item.Value == true && ItemsToCompare.Contains(item.Key))
AllCorrect.Add(item.Key);
}
AllCorrect.Sort();
Can be reduced to :
List<string> AllCorect = ImportData.Where(vp =>
ItemsToCompare.Contains(vp.Key) && vp.Value).Select(vp => vp.Key).OrderBy(vp => vp).ToList();
To solve the second problem you can do :
return AllDrawings.First(l => l.Value.OrderBy(l2 => l2).SequenceEqual(AllCorect)).Key;
P.S.
If First() always throws an exception then it suggests that problem lays in how this lists are filled with values and this is a different question.
Example :
public static string GetDrawing(Dictionary<string, List<string>> AllDrawings, Dictionary<string, bool> ImportData, string[] ItemsToCompare)
{
List<string> AllCorect = ImportData.Where(vp =>
ItemsToCompare.Contains(vp.Key) && vp.Value).Select(vp => vp.Key).OrderBy(vp => vp).ToList();
return AllDrawings.First(l => l.Value.OrderBy(l2 => l2).SequenceEqual(AllCorect)).Key;
}
static void Main(string[] args)
{
List<string> list1 = new List<string>() { "one", "two", "three" };
List<string> list2 = new List<string>() { "five", "six", "seven" };
Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>()
{
{"first", list1}, {"second", list2}
};
string[] itemsToCompare = { "one", "two", "three" };
var dict2 = new Dictionary<string, bool>()
{
{"one", true},
{"two", true},
{"three", true}
};
var result = GetDrawing(dict, dict2, itemsToCompare);
Console.WriteLine(result);
}
Output : first
If the strings really match also for casing your code would be correct. I propose you inspect your string sequences - create an readable string and add appropriate break points. Also try to sort case-insensitive if that is what is missing here
AllCorrect.Sort(StringComparer.InvariantCultureIgnoreCase);
var AllCorrectInfo = string.Join(", ", AllCorrect.ToArray());
foreach (var DrawItem in AllDrawings)
{
DrawItem.Value.Sort();
var DrawItemInfo = string.Join(", ", DrawItem.Value.ToArray());
var match = AllCorrect.SequenceEqual(DrawItem.Value, StringComparer.InvariantCultureIgnoreCase);
if (match == true)
{
FinalDrawing = DrawItem.Key;
}
}

How to split list into all the cases sublists using LINQ?

I would like to to split list into all the cases SubLists using LINQ?
For example :
List contains : {"a", "b", "c"}
I would like to make list of lists where the result is : {"a", "ab", "abc"}
public List<List<Alphabet>> ListofLists (Stack<String> Pile)
{
var listoflists = new List<List<Alphabet>>();
var list = new List<Alphabet>();
foreach (var temp in from value in Pile where value != "#" select new Alphabet(value))
{
list.Add(temp);
listoflists.Add(list);
}
return listoflists;
}
This method will allow you to do this.
IEnumerable<IEnumerable<T>> SublistSplit<T>(this IEnumerable<T> source)
{
if (source == null) return null;
var list = source.ToArray();
for (int i = 0; i < list.Length; i++)
{
yield return new ArraySegment<T>(list, 0, i);
}
}
In case of strings:
IEnumerable<string> SublistSplit<T>(this IEnumerable<string> source)
{
if (source == null) return null;
var sb = new StringBuilder();
foreach (var x in source)
{
sb.Append(x);
yield return sb.ToString();
}
}
If you want to yield the intermediate values of an accumulation you could define your own extension method:
public IEnumerable<TAcc> Scan<T, TAcc>(this IEnumerable<T> seq, TAcc init, Func<T, TAcc, TAcc> acc)
{
TAcc current = init;
foreach(T item in seq)
{
current = acc(item, current);
yield return current;
}
}
then your example would be:
var strings = new[] {"a", "b", "c"}.Scan("", (str, acc) => str + acc);
for lists, you'll have to copy them each time:
List<Alphabet> input = //
List<List<Alphabet>> output = input.Scan(new List<Alphabet>(), (a, acc) => new List<Alphabet(acc) { a }).ToList();
Note that copying the intermediate List<T> instances could be inefficient, so you may want to consider using an immutable structure instead.

Categories