C# arbitrary nested Lists - c#

In Python I can convert a binary tree structure to an arbitrary nested List:
great
/ \
gr eat
/ \ / \
g r e at
/ \
a t
[great, [gr, [g, r], eat, [e, at, [a, t]]]
Is there a way to build an arbitrary nested List in C#?
EDIT: I took a BinaryTree<T> class from MSDN docs as a base class for my custom StrBinaryTree class. Method FormTree is doing a job for creating a tree structure from a string:
public class StrBinaryTree : BinaryTree<string>
{
public StrBinaryTree(string data)
{
if (data.Length == 0)
{
base.Root = null;
base.Count = 0;
}
else
{
base.Root = new BinaryTreeNode<string>();
base.Root.Data = data;
base.Count = 1;
}
}
public void FormTree(BinaryTreeNode<string> node)
{
var subLength = node.Data.Length / 2;
if (subLength == 0)
return;
node.Left = new BinaryTreeNode<string>(node.Data.Substring(0, subLength));
node.Right = new BinaryTreeNode<string>(node.Data.Substring(subLength));
base.Count += 2;
FormTree(node.Left);
FormTree(node.Right);
}
...}

I would use recursion to go through the tree. Since you didn't told us the type of the tree we cannot provide you c# sample code.
But it would be something like this:
void List<Object> GetNestedListFromTree(Tree tree, List<Object> list = null)
{
List<Object> curList;
if (!tree.HasChildNodes)
return list;
else
{
if (list==null)
{
list = new List<Object>;
curList = list;
}
else
{
curList = new List<Object>;
list.Add(curList);
}
foreach(node in tree.ChildNodes)
{
curList.Add(node.Name);
curList.Add(GetNestedListFromTree(node.GetSubtree, curList));
}
return curList;
}
}
This isn't tested because I don't know your tree but yeah ... It should work if your tree can provide the needed functionality.

Try this solution
public static List<object> Solve(string input, List<object> list = null)
{
if (list == null)
return Solve(input, new List<object> { input });
if (input.Length > 1)
{
var middle = input.Length / 2;
var first = input.Substring(0, middle);
var second = input.Substring(middle);
var innerList = new List<object>();
list.Add(innerList);
foreach (var side in new[] { first, second })
{
innerList.Add(side);
Solve(side, innerList);
}
}
return list;
}
public static void Show(object input)
{
if (!(input is string))
{
Console.Write("[");
var list = input as List<object>;
foreach (var item in list)
{
Show(item);
if (item != list.Last())
Console.Write(", ");
}
Console.Write("]");
}
else
Console.Write(input);
}
Usage:
var result = Solve("great");
Show(result);//[great, [gr, [g, r], eat, [e, at, [a, t]]]]
Approximate code for BinaryTreeNode:
public static BinaryTreeNode<string> Solve(BinaryTreeNode<string> node)
{
if(node.Data.Length > 1)
{
var middle = node.Data.Length / 2;
var left = node.Data.Substring(0, middle);
var right = node.Data.Substring(middle);
node.Left = Solve(new BinaryTreeNode<string>(left));
node.Right = Solve(new BinaryTreeNode<string>(right));
}
return node;
}
Usage:
var result = Solve(new BinaryTreeNode<string>("great"));

Try this:
public Tree<string> Build(string text)
{
var tree = new Tree<string>() { Value = text };
if (text.Length > 1)
{
tree.Add(Build(text.Substring(0, text.Length / 2)));
tree.Add(Build(text.Substring(text.Length / 2)));
}
return tree;
}
public class Tree<T> : List<Tree<T>>
{
public T Value;
public override string ToString()
{
var r = $"\"{this.Value}\"";
if (this.Any())
{
r += $" [{String.Join(", ", this.Select(t => t.ToString()))}]";
}
return r;
}
}
When I run Build("great") I get:
"great" ["gr" ["g", "r"], "eat" ["e", "at" ["a", "t"]]]

Related

C# intersect with lists

Working on a leetcode.com problem I tried the following approach with included the correct results with one duplicate. The code is supposed to find all possibilities of 3 numbers that equal zero without any duplicates.
I am looking for dupes in a list of lists using this if statement:
if(!returnList.Where(x=>x.Intersect(fullResult).Count()==3).Any())
This filters dupes in all but one case. Does anyone know why or perhaps a better way to eliminate dupes from a list of lists?
it will consistently not filter -1, -1, 2 which is a valid set but returned 2 times.
Paste into a console app to recreate.
class Program
{
static void Main(string[] args)
{
var output = ThreeSum(new int[] { -1, 0, 1, 2, -1, -4 });
foreach(var outie in output)
Console.WriteLine(String.Format("{0}, {1}, {2}", outie[0], outie[1], outie[2]));
Console.Read();
}
static public IList<IList<int>> ThreeSum(int[] nums)
{
List<int> lookup = new List<int>();
foreach (int i in nums)
{
lookup.Add(i);
}
IList<IList<int>> returnList = new List<IList<int>>();
for (var i = 0; i < nums.Count(); i++)
{
var result = TwoSum(i, lookup);
if (result != null)
{
var fullResult = new List<int>() { nums[i], nums[result[0]], nums[result[1]] };
if(!returnList.Where(x=>x.Intersect(fullResult).Count()==3).Any())
{
returnList.Add(fullResult);
}
}
}
return returnList;
}
static private int[] TwoSum(int thirdnumIndex, List<int> nums)
{
var target = nums[thirdnumIndex];
for (var i = 0; i < nums.Count(); i++)
{
var comp = (target + nums[i]) * -1;
if (nums.Contains(comp))
{
var indexOfComp = nums.IndexOf(comp);
if (indexOfComp == i || indexOfComp == thirdnumIndex)
{
return null;
}
return new int[] { i, indexOfComp };
}
}
return null;
}
}
Using Sort and SequenceEqual should work
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
var output = ThreeSum(new int[] { -1, 0, 1, 2, -1, -4 });
foreach (var outie in output)
{
Console.WriteLine($"{outie[0]}, {outie[1]}, {outie[2]}");
}
Console.Read();
}
private static IList<IList<int>> ThreeSum(int[] nums)
{
var lookup = new List<int>(nums);
var returnList = new List<IList<int>>();
for (var i = 0; i < nums.Length; i++)
{
var result = TwoSum(i, lookup);
if (result != null)
{
var fullResult = new List<int> { nums[i], nums[result[0]], nums[result[1]] };
fullResult.Sort();
if (!returnList.Any(b => b.SequenceEqual(fullResult)))
{
returnList.Add(fullResult);
}
}
}
return returnList;
}
private static int[] TwoSum(int thirdnumIndex, List<int> nums)
{
var target = nums[thirdnumIndex];
for (var i = 0; i < nums.Count; i++)
{
var comp = (target + nums[i]) * -1;
if (nums.Contains(comp))
{
var indexOfComp = nums.IndexOf(comp);
if (indexOfComp == i || indexOfComp == thirdnumIndex)
{
return null;
}
return new[] { i, indexOfComp };
}
}
return null;
}
}

Sort Array on on Value Difference

I Have An Array,for example
string[] stArr= new string[5] { "1#3", "19#24", "10#12", "13#18", "20#21" };
i want to sort this array on
3-1=2;
24-19=5;
12-10=2;
18-13=5;
21-20=1;
and the sorting result should be like
string[] stArr= new string[5] { "20#21", "1#3", "10#12", "13#18", "20#21" };
I have to find the solution for all possible cases.
1>length of the array is not fixed(element in the array)
2>y always greater than x e.g x#y
3> i can not use list
You can use LINQ:
var sorted = stArr.OrderBy(s => s.Split('#')
.Select(n => Int32.Parse(n))
.Reverse()
.Aggregate((first,second) => first - second));
For Your Case:
stArr = stArr.OrderBy(s => s.Split('#')
.Select(n => Int32.Parse(n))
.Reverse()
.Aggregate((first,second) => first - second)).ToArray();
try this
string[] stArr = new string[5] { "1#3", "19#24", "10#12", "13#18", "20#21" };
Array.Sort(stArr, new Comparison<string>(compare));
int compare(string z, string t)
{
var xarr = z.Split('#');
var yarr = t.Split('#');
var x1 = int.Parse(xarr[0]);
var y1 = int.Parse(xarr[1]);
var x2 = int.Parse(yarr[0]);
var y2 = int.Parse(yarr[1]);
return (y1 - x1).CompareTo(y2 - x2);
}
Solving this problem is identical to solving any other sorting problem where the order is to be specified by your code - you have to write a custom comparison method, and pass it to the built-in sorter.
In your situation, it means writing something like this:
private static int FindDiff(string s) {
// Split the string at #
// Parse both sides as int
// return rightSide-leftSide
}
private static int CompareDiff(string a, string b) {
return FindDiff(a).CompareTo(FindDiff(b));
}
public static void Main() {
... // Prepare your array
string[] stArr = ...
Array.Sort(stArr, CompareDiff);
}
This approach uses Array.Sort overload with the Comparison<T> delegate implemented in the CompareDiff method. The heart of the solution is the FindDiff method, which takes a string, and produces a numeric value which must be used for comparison.
you can try the following ( using traditional way)
public class Program
{
public static void Main()
{
string[] strArr= new string[5] { "1#3", "19#24", "10#12", "13#18", "20#21" };
var list = new List<Item>();
foreach(var item in strArr){
list.Add(new Item(item));
}
strArr = list.OrderBy(t=>t.Sort).Select(t=>t.Value).ToArray();
foreach(var item in strArr)
Console.WriteLine(item);
}
}
public class Item
{
public Item(string str)
{
var split = str.Split('#');
A = Convert.ToInt32(split[0]);
B = Convert.ToInt32(split[1]);
}
public int A{get; set;}
public int B{get; set;}
public int Sort { get { return Math.Abs(B - A);}}
public string Value { get { return string.Format("{0}#{1}",B,A); }}
}
here a working demo
hope it will help you
Without LINQ and Lists :) Old School.
static void Sort(string [] strArray)
{
try
{
string[] order = new string[strArray.Length];
string[] sortedarray = new string[strArray.Length];
for (int i = 0; i < strArray.Length; i++)
{
string[] values = strArray[i].ToString().Split('#');
int index=int.Parse(values[1].ToString()) - int.Parse(values[0].ToString());
order[i] = strArray[i].ToString() + "," + index;
}
for (int i = 0; i < order.Length; i++)
{
string[] values2 = order[i].ToString().Split(',');
if (sortedarray[int.Parse(values2[1].ToString())-1] == null)
{
sortedarray[int.Parse(values2[1].ToString())-1] = values2[0].ToString();
}
else
{
if ((int.Parse(values2[1].ToString())) >= sortedarray.Length)
{
sortedarray[(int.Parse(values2[1].ToString())-1) - 1] = values2[0].ToString();
}
else if ((int.Parse(values2[1].ToString())) < sortedarray.Length)
{
sortedarray[(int.Parse(values2[1].ToString())-1) + 1] = values2[0].ToString();
}
}
}
for (int i = 0; i < sortedarray.Length; i++)
{
Console.WriteLine(sortedarray[i]);
}
Console.Read();
}
catch (Exception ex)
{
throw;
}
finally
{
}

How to find the next element in a generic List?

This is my Generic List:
public class TagType
{
public string FieldTag;
public int Position;
}
List<TagType<dynamic>> TagList = new List<TagType<dynamic>>();
TagList.Add(new TagType<dynamic>() { FieldTag = "ID", Position = posIdStr });
TagList.Add(new TagType<dynamic>() { FieldTag = "PT", Position = posPtStr });
TagList.Add(new TagType<dynamic>() { FieldTag = "ID", Position = posIdStr });
TagList.Add(new TagType<dynamic>() { FieldTag = "EC", Position = posECStr });
I am trying to get Position value for the FieldTag that comes after (for eg: PT).
How do I do this?
You find the index of PT and add 1? (but remember to check that the index + 1 < the length of the List)
// Find the index of PT
int ix = TagList.FindIndex(x => x.FieldTag == "PT");
// index found
if (ix != -1)
{
// Check that index + 1 < the length of the List
if (ix + 1 < TagList.Count)
{
var position = TagList[ix + 1]; // Add 1
}
}
Unfortunately each time you do a search you will have to iterate over the list, find the field tag you are looking for, then go to the next element and get the position value. e..: An O(n) for lookup solution:
private static object SearchPosition(List<TagType<object>> tagList, string fieldTag)
{
var i = tagList.FindIndex(x => x.FieldTag == "PT");
if (i >= 0 && i < tagList.Count)
{
return tagList[i + 1].Position;
}
}
And test:
[Test]
public void FieldTagTest()
{
var res = SearchPosition(_tagList, "PT");
res.ToString().Should().Be("ID2");
}
If your list does not change often, you should build a Dictionary<string,int> with the FieldTag as Keyand the list index position as value. Ofcourse each time you modify the list you would need to build this index again.
An O(1) solution is:
private static object SearchPositionUsingIndex(List<TagType<object>> tagList, string fieldTag)
{
// You would save this index, and build it only once,
// or rebuild it whenver something changes.
// you could implement custom index modifications.
var index = BuildIndex(tagList);
int i;
if (!index.TryGetValue(fieldTag, out i)) return null;
if (i + 1 >= tagList.Count) return null;
return tagList[i + 1].Position;
}
private static Dictionary<string, int> BuildIndex(List<TagType<object>> tagList)
{
var index = new Dictionary<string, int>();
for (int i = 0; i < tagList.Count; i++)
{
var tag = tagList[i];
if (!index.ContainsKey(tag.FieldTag)) index.Add(tag.FieldTag, i);
}
return index;
}
And test:
[Test]
public void FieldTagTestUsingIndex()
{
var res = SearchPositionUsingIndex(_tagList, "PT");
res.ToString().Should().Be("ID2");
}
Or you could use a 1 line LINQ method, which is also O(n):
[Test]
public void FieldTagTestLinq()
{
var res = SearchUsingLinq();
res.ToString().Should().Be("ID2");
}
private object SearchUsingLinq()
{
var p = _tagList.SkipWhile(x => x.FieldTag != "PT").Skip(1).FirstOrDefault();
return p != null ? p.Position : null;
}
TestSetup
public class SO29047477
{
private List<TagType<object>> _tagList;
[SetUp]
public void TestSetup()
{
_tagList = new List<TagType<dynamic>>();
_tagList.Add(new TagType<dynamic>() { FieldTag = "ID", Position = "ID1"});
_tagList.Add(new TagType<dynamic>() { FieldTag = "PT", Position = "PT1" });
_tagList.Add(new TagType<dynamic>() { FieldTag = "ID", Position = "ID2" });
_tagList.Add(new TagType<dynamic>() { FieldTag = "EC", Position = "EC1" });
}
}
If you want to get next element's Position after each item with FieldTag PT, then you can solve it in one or two lines with LINQ:
var resultTag = TagList.SkipWhile(x => x.FieldTag != "PT").Skip(1).FirstOrDefault();
var resultPosition = resultTag == null ? 0 : resultTag.Position;
Additional:
If you want to cast it to int then just cast it explicitly.
var resultTag = TagList.SkipWhile(x => x.FieldTag != "PT").Skip(1).FirstOrDefault();
int resultPosition = resultTag == null ? 0 : (int)resultTag.Position;
public Position? GetNextPosition(string FieldTagVal)
{
bool returnNext = false;
foreach(TagType t in TagList)
{
if (returnNext) return t.Position;
if (t.FieldTag == FieldTagVal) returnNext = true;
}
return null;
}

Connect element in distinct array using recursion

if I have two array
A:[A,B]
B:[1,2,3]
how can I create a string List like [A_1, A_2, A_3, B_1, B_2, B_3]
the number of array is not regular, it's maybe have 3 more
A:[A,B]
B:[1,2,3]
C:[w,x,y,z]
D:[m,n]
E:[p,q,r]
can I use recursive to solve it?
So, we define a functions Mergethat takes lists of list of stings and merges them into the string enumerable you want
static void Main(string[] args)
{
var a = new[] { "A", "B" };
var b = new[] { "1", "2", "3" };
var c = new[] { "x", "y", "z", "w" };
var result = Merge(a, b, c);
foreach (var r in result)
{
Console.WriteLine(r);
}
}
public static IList<string> Merge(params IEnumerable<string>[] lists)
{
return Merge((IEnumerable<IEnumerable<string>>) lists);
}
public static IList<string> Merge(IEnumerable<IEnumerable<string>> lists)
{
var retval = new List<string>();
var first = lists.FirstOrDefault();
if (first != null)
{
var result = Merge(lists.Skip(1));
if (result.Count > 0)
{
foreach (var x in first)
{
retval.AddRange(result.Select(y => string.Format("{0}_{1}", x, y)));
}
}
else
{
retval.AddRange(first);
}
}
return retval;
}
we can also improve this, if you use Lists as inputs
public static IList<string> Merge(params IList<string>[] lists)
{
return Merge((IList<IList<string>>) lists);
}
public static IList<string> Merge(IList<IList<string>> lists, int offset = 0)
{
if (offset >= lists.Count)
return new List<string>();
var current = lists[offset];
if (offset + 1 == lists.Count) // last entry in lists
return current;
var retval = new List<string>();
var merged = Merge(lists, offset + 1);
foreach (var x in current)
{
retval.AddRange(merged.Select(y => string.Format("{0}_{1}", x, y)));
}
return retval;
}
This is simple iterating over n-ary dimension - no need for recursion for that, just array to store indexes.
static void Iterate(int[] iterators, ArrayList[] arrays) {
for (var j = iterators.Length - 1; j >= 0; j--) {
iterators[j]++;
if (iterators[j] == arrays[j].Count) {
if (j == 0) {
break;
}
iterators[j] = 0;
} else {
break;
}
}
}
static IList<string> Merge(ArrayList[] arrays) {
List<string> result = new List<string>();
int[] iterators = new int[arrays.Length];
while (iterators[0] != arrays[0].Count) {
var builder = new StringBuilder(20);
for(var index = 0; index < arrays.Length; index++) {
if (index > 0) {
builder.Append("_");
}
builder.Append(arrays[index][iterators[index]]);
}
result.Add(builder.ToString());
Iterate(iterators, arrays);
}
return result;
}
static void Main(string[] args) {
var list1 = new ArrayList();
var list2 = new ArrayList();
var list3 = new ArrayList();
list1.Add(1);
list1.Add(2);
list2.Add("a");
list2.Add("b");
list3.Add("x");
list3.Add("y");
list3.Add("z");
var result = Merge(new[] { list1, list2, list3 });
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace arrconn {
class Program {
static string[] conn(params Array[] arrs) {
if(arrs.Length == 0) return new string[0];
if(arrs.Length == 1) {
string[] result = new string[arrs[0].Length];
for(int i = 0; i < result.Length; i++)
result[i] = arrs[0].GetValue(i).ToString();
return result; }
else {
string[] result = new string[arrs[0].Length*arrs[1].Length];
for(int i = 0; i < arrs[0].Length; i++)
for(int j = 0; j < arrs[1].Length; j++)
result[i*arrs[1].Length+j] = string.Format("{0}_{1}", arrs[0].GetValue(i), arrs[1].GetValue(j));
if(arrs.Length == 2) return result;
Array[] next = new Array[arrs.Length-1];
next[0] = result; Array.Copy(arrs, 2, next, 1, next.Length-1);
return conn(next);
}
}
static void Main(string[] args) {
foreach(string s in conn(
new string[] { "A", "B" },
new int[] { 1, 2, 3 },
new string[] { "x" },
new string[] { "$", "%", "#" }))
Console.WriteLine(s);
Console.Read();
}
}
}
I guess your input are like this:
var A = ["A","B"];
var B = [1,2,3];
var C = ["x","y","z","w"];
And what you want to obtain is:
var result = ["A_1_x", "A_1_y",...
"A_2_x", "A_2_y",...
"A_3_x", "A_3_y",...
"B_1_x", "B_1_y",...
...
..., "B_3_z", "B_3_w"];
We'll be working with IEnumerable as it will simplify the work for us and give us access to the yield keyword.
First, let's take care of the case where we only concataining two collections:
IEnumerable<string> ConcatEnumerables(IEnumerable<object> first, IEnumerable<object> second)
{
foreach (var x in first)
{
foreach (var y in second)
{
yield return x.ToString() + "_" + y.ToString();
}
}
}
Then we can recursively takle any number of collections:
IEnumerable<string> ConcatEnumerablesRec(IEnumerable<IEnumerable<object>> enums)
{
//base cases
if(!enums.Any())
{
return Enumerable.Empty<string>();
}
if (enums.Count() == 1)
{
return enums.First().Select(o => o.ToString());
}
//recursively solve the problem
return ConcatEnumerables(enums.First(), ConcatEnumerablesRec(enums.Skip(1));
}
Now you just need to call ToArray on the result if you really need an array as your output.
string[] Concatenator(params object[][] parameters)
{
return ConcatEnumerablesRec(parameters).ToArray();
}
This should do the trick. Note that the input sequences do not have to be arrays - they can be any type that implements IEnumerable<>.
Also note that we have to case sequences of value types to sequences of <object> so that they are assignable to IEnumerable<object>.
Here's the compilable Console app demo code:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
internal static class Program
{
static void Main()
{
string[] a = {"A", "B", "C", "D"};
var b = Enumerable.Range(1, 3); // <-- See how it doesn't need to be an array.
char[] c = {'X', 'Y', 'Z'};
double[] d = {-0.1, -0.2};
var sequences = new [] { a, b.Cast<object>(), c.Cast<object>(), d.Cast<object>() };
Console.WriteLine(string.Join("\n", Combine("", sequences)));
}
public static IEnumerable<string> Combine(string prefix, IEnumerable<IEnumerable<object>> sequences)
{
foreach (var item in sequences.First())
{
string current = (prefix == "") ? item.ToString() : prefix + "_" + item;
var remaining = sequences.Skip(1);
if (!remaining.Any())
{
yield return current;
}
else
{
foreach (var s in Combine(current, remaining))
yield return s;
}
}
}
}
}

C# (String.StartsWith && !String.EndsWith && !String.Contains) using a List

I am a newbie in C#, and I am having problems.
I have 2 List, 2 strings and a getCombinations(string) method that
returns all combinations of a string as List;
How do i validate if a subjectStrings element does not
StartWith && !EndsWith && !Contains (or !StartWith && !EndsWith && Contains, etc.)
for every combinations of startswithString, endswithString and containsString?
Here is my code in StartWith && !EndsWith
(if you want to see it running: http://ideone.com/y8JZkK)
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
public static void Main()
{
List<string> validatedStrings = new List<string>();
List<string> subjectStrings = new List<string>()
{
"con", "cot", "eon", "net", "not", "one", "ten", "toe", "ton",
"cent", "cone", "conn", "cote", "neon", "none", "note", "once", "tone",
"cento", "conte", "nonce", "nonet", "oncet", "tenon", "tonne",
"nocent","concent", "connect"
}; //got a more longer wordlist
string startswithString = "co";
string endswithString = "et";
foreach(var z in subjectStrings)
{
bool valid = false;
foreach(var a in getCombinations(startswithString))
{
foreach(var b in getCombinations(endswithString))
{
if(z.StartsWith(a) && !z.EndsWith(b))
{
valid = true;
break;
}
}
if(valid)
{
break;
}
}
if(valid)
{
validatedStrings.Add(z);
}
}
foreach(var a in validatedStrings)
{
Console.WriteLine(a);
}
Console.WriteLine("\nDone");
}
static List<string> getCombinations(string s)
{
//Code that calculates combinations
return Permutations.Permutate(s);
}
}
public class Permutations
{
private static List<List<string>> allCombinations;
private static void CalculateCombinations(string word, List<string> temp)
{
if (temp.Count == word.Length)
{
List<string> clone = temp.ToList();
if (clone.Distinct().Count() == clone.Count)
{
allCombinations.Add(clone);
}
return;
}
for (int i = 0; i < word.Length; i++)
{
temp.Add(word[i].ToString());
CalculateCombinations(word, temp);
temp.RemoveAt(temp.Count - 1);
}
}
public static List<string> Permutate(string str)
{
allCombinations = new List<List<string>>();
CalculateCombinations(str, new List<string>());
List<string> combinations = new List<string>();
foreach(var a in allCombinations)
{
string c = "";
foreach(var b in a)
{
c+=b;
}
combinations.Add(c);
}
return combinations;
}
}
Output:
con
cot
cone
conn
cote <<<
conte <<<
concent
connect
Done
if(z.StartsWith(a) && !z.EndsWith(b))
var b can be "et" and "te", but cote and conte endswith "te",
why it is still added in my validated strings?
Thanks in advance.
z.StartsWith(a) && !z.EndsWith(b)
check below combination
z ="cote"
a ="co"
b ="te"
so z start with "co" and z not end with "te", your condition pass and cote will add to list
i would try as below
var sw =getCombinations(startswithString);
var ew = getCombinations(endswithString);
var result = subjectStrings.Where(z=>
sw.Any(x=>z.StartsWith(x) &&
!ew.Any(y=>z.EndsWith(y))))
.ToList();
DEMO
output :
con
cot
cone
conn
concent
connect
foreach(var b in getCombinations(endswithString))
{
if(z.StartsWith(a) && !z.EndsWith(b))
{
valid = true;
break;
}
}
here you are setting valid to true as soon as there is match for !z.EndsWith(b) and you are not traversing the whole list of permutations available.
since "cote" doesn't end with "et" it is a match and valid is set to true and the code breaks.
So that's why "cote" is added to your list of valid strings. So is the case with "conte".
What you want to do is :
List<string> startsWithCombination = getCombinations("co");
List<string> endsWithCombination = getCombinations("et");
foreach (var z in subjectStrings)
{
bool isStartMatchFound = startsWithCombination.Any(b => z.StartsWith(b));
if (isStartMatchFound)
{
bool isEndMatchFound = endsWithCombination.Any(b => z.EndsWith(b));
if (!isEndMatchFound)
{
validatedStrings.Add(z);
}
}
}

Categories