fill lists with another list with conditions [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have a list:
List<string> letters = {"a", "b", "c", "d", "e", "f"};
and I have another lists that contains another strings:
List<string> myList1 = { "f3", "g4", "h5" };
List<string> myList2 = { "z5", "w7", "q9" };
List<string> myList3 = { "k5", "n7" };
I want to fill myLists with letters list with conditions:
Every list can contain 5 elements in total and don't add a letter twice for the same list.
In the example above,
myList1 = { "f3", "g4", "h5", "a", "b"};
myList2 = { "z5", "w7", "q9", "c", "d"};
myList3 = { "k5", "n7", "e", "f", "d" };
regarding to myList3, d was added randomly (don't forget that I don't want to add "e" or "f" twice).
Please note that if I had this case:
List<string> myList1 = { "f3", "g4", "h5", "t3", "u6" };
List<string> myList2 = { "z5", "w7", "q9", "k9" };
List<string> myList3 = { "k5", "n7", "d3", "n6" };
The output is:
myList1 = { "f3", "g4", "h5", "t3", "u6" };
myList2 = { "z5", "w7", "q9", "k9", "a" };
myList3 = { "k5", "n7", "d3", "n6", "b" };
If it helps, myList1 has more/equal elements than myList2 and myList3 when it's declared.
I tried to do it, but I have lots of conditions that it's unreadable.
Any help appreciated.

There is lot of ways to approach it, would have been better had you shared your approach and we could help you with it. Anyways,following is one approach you could opt.
You could write an extension method called Fill.
public static class Extension
{
public static IEnumerable<T> Circle<T>(this IEnumerable<T> list, int startIndex)
{
return list.Skip(startIndex).Concat(list.Take(startIndex));
}
public static void Fill<T>(this List<T> source, List<T> reference, int maxCount,ref int index)
{
if(source.Count() >= maxCount) return;
var difference = source.Count() - maxCount;
var newReferenceList = reference.Circle(index);
source.AddRange(newReferenceList.Where(x=>!source.Contains(x)).Take(maxCount- source.Count()));
index+=Math.Abs(difference);
if(index > maxCount) index = 0;
}
}
And then in your client,
int index = 0;
myList1.Fill(letters,5,ref index);
myList2.Fill(letters,5,ref index);
myList3.Fill(letters,5,ref index);

I think that this is what you are looking for:
public MainWindow()
{
InitializeComponent();
letters = new List<string> { "a", "b", "c", "d", "e", "f" };
myList1 = new List<string> { "f3", "g4", "h5" };
myList2 = new List<string> { "z5", "w7", "q9" };
myList3 = new List<string> { "k5", "n7" };
FillLists(letters, new List<List<string>> { myList1, myList2, myList3 });
}
private void FillLists(List<string> listToFillWith, List<List<string>> allLists)
{
char lastItemInList = listToFillWith.Last()[0]; //We get the last item inside the listToFillWith list and with the [0] we convert this string to a char
foreach (List<string> list in allLists) //We loop through each list inside allLists
{
while(list.Count != 5) //While either list 1, 2 or 3 does not have 5 items
{
if (listToFillWith.Count > 0) //Make sure our listToFillWith still has items to fill our list
{
list.Add(listToFillWith[0]); //Add the first item from listToFillWith to our list
listToFillWith.Remove(listToFillWith[0]); //Remove the first item from listToFillWith so we don't add it again
}
else //If listToFillWith is empty
{
char nextLetter;
//Here we check if the last item in the listToFillWith is a Z or z
if (lastItemInList == 'z')
{
nextLetter = 'a';
}
else if (lastItemInList == 'Z')
{
nextLetter = 'A';
}
else //If the last item in the listToFillWith is not a Z or z we get the last letter and go to the next letter in the alphabet
{
nextLetter = (char)(((int)lastItemInList) + 1);
}
list.Add(nextLetter.ToString()); //Add the next letter in the alphabet to the list
}
}
}
}

Related

How to check if an element inside a List of string array exists in another List of string array

I basically want to know if a string array from one list exists in another list of string array
So for example:
List 1:
{"A", "R1"}
{"A", "R2"}
List 2:
{"A", "R1"}
{"B", "R1"}
{"B", "R2"}
Then If I loop in List 1 to check whether it exists in List 2 the results will be:
true
false
I want to do it in LINQ if possilbe
You can use
Any and SequenceEqual
for this.
using System.Collections.Generic;
List<string[]> testSet = new List<string[]>
{
new string[] { "A", "R1" },
new string[] { "A", "R2" }
};
List<string[]> resultSet = new List<string[]>
{
new string[] { "A", "R1" },
new string[] { "B", "R1" },
new string[] { "B", "R2" }
};
// Checks if the value is found anywhere in the list
bool IsArrayInList(string[] value, List<string[]> list)
{
return list.Any(value.SequenceEqual);
}
foreach (var val in testSet)
{
Console.WriteLine(IsArrayInList(val,resultSet));
}
Console.ReadLine();
I would suggest a combination of .Any() and .SequenceEqual() or .All()
Example:
var list1 = new string[][]
{
new string[] { "A", "R1" },
new string[] { "A", "R2" },
};
var list2 = new string[][]
{
new string[] { "A", "R1"},
new string[] { "B", "R1"},
new string[] { "B", "R2"},
};
var itemToFind = list1.First();
// Option 1
var isInList2 = list2.Any(i => i.SequenceEqual(itemToFind));
// Option 2
var isInList2Option2 = list2.Any(item => item.All(innerItem => itemToFind.Contains(innerItem)));
As-needed, you can improve these to account for ordering, case-insensitivity, exact number of arguments, etc...
Option 1 will find any matches where the inner sequence is in the same order, same-casing as what you are looking for.
Option 2 will find any matches where the inner sequence contains all of the values of the sequence you are checking for.
Hopefully this points you in the right direction at least.

Using "foreach" in string array c# [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Good Morning,
I need a foreach loop to print the sequence below line by line:
loop1 a0,a1,a2
loop2 b0,b1,b2
loop3 c0,c1,c2
This is my first post, so sorry for any lack of information.
private void button1_Click(object sender, EventArgs e)
{
int col0_int = 0;
var col0_elements = new string[] { "a0", "b0", "c0", "d0", "e0", "f0", "g0", "h0", };
IList<string> col0_all = col0_elements;
String[] col0_list = new String[col0_all.Count];
List<string> col0_each = new List<string>();
foreach (string element in col0_elements)
{
col0_list[col0_int++] = element;
col0_each.Add(element);
}
int col1_int = 0;
var col1_elements = new string[] { "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", };
IList<string> col1_all = col1_elements;
String[] col1_list = new String[col1_all.Count];
List<string> col1_each = new List<string>();
foreach (string element in col1_elements)
{
col1_list[col1_int++] = element;
col1_each.Add(element);
}
int col2_int = 0;
var col2_elements = new string[] { "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", };
IList<string> col2_all = col2_elements;
String[] col2_list = new String[col2_all.Count];
List<string> col2_each = new List<string>();
foreach (string element in col2_elements)
{
col2_list[col2_int++] = element;
col2_each.Add(element);
}
//LOOP script here
}
Assuming all arrays are equal length:
for (int i = 0; i < col0_list.Length; i++)
{
Console.WriteLine($"{col0_all[i]},{col1_all[i]},{col2_all[i]}");
}
If you can ensure that your three lists always contain the required elements at the correct position, a fast solution would be to use the LINQ Enumerable.Zip extension method two times:
var results = col0_elements.Zip(col1_elements, (x, y) => $"{x}, {y}")
.Zip(col2_elements, (x, y) => $"{x}, {y}");
This produces an IEnumerable<string> (over which you can loop) with the following content:
{
"a0, a1, a2",
"b0, b1, b2",
"c0, c1, c2",
"d0, d1, d2",
"e0, e1, e2",
"f0, f1, f2",
"g0, g1, g2",
"h0, h1, h2"
}
You are overcomplicating the things.
For each string array you are creating an empty string array and a list with only one element...
With this approach you are esentially creating a string matrix.
var col0_elements = new string[] { "a0", "b0", "c0", "d0", "e0", "f0", "g0", "h0", };
var col1_elements = new string[] { "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", };
var col2_elements = new string[] { "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", };
IList<string[]> all_elements = new List<string[]>{ col0_elements, col1_elements, col2_elements };
for (int i = 0; i < col0_elements.Length; i++) // Row iteration
{
foreach (var cell in all_elements) // Cell iteration
{
Console.Write(cell[i]);
}
Console.WriteLine();
}
You can get those with a for loop:
for (int index = 0; index < col0_each.Count; index++)
{
string col0String = col0_each[index];
string col1String = col1_each[index];
string col2String = col2_each[index];
(print as desired);
}
This code doesn't include any error checking to make sure each list is long enough; it assumes they are all the same length.
There are extra lists in the code that could be simplified, though that's not what you asked about.

check if list ordered according to another list c#

I have a list of strings, which is ordered with a particular method :
list1 : { "E", "C", "B", "A"};
Now I want to check other arrays that if it was ordered according to list1, then it is correct.
for example :
array: { "A", "C", "E", "B" } //false - not ordered according to list1
array: { "E", "B", "C" } //false - not ordered according to list1
array: { "C", "A"} //true- ordered according to list1
Function codes:
List<string> list1 = new List<string> { "E", "C", "B", "A"};
public static bool IsSorted(string[] array)
{
for (int i = 0; i < array.Length; i++)
{
if () //Your opinion
{
return false;
}
}
return true;
}
I think it's easy using Lists instead of array
Here is an example :
List<int> list1 = new List<int>();
list1.Add(1);
list1.Add(2);
list1.Add(3);
List<int> list2 = new List<int>();
list2.Add(2);
list2.Add(3);
Console.WriteLine( list1.Intersect(list2).SequenceEqual(list2)); // Will return true
Posted an example about int variables according to your example, You can use what ever type you want
UPDATE : It works well with arrays too ( Thanks to #Matthew Watson)
int[] arr1 = { 1, 2, 3 };
int[] arr2 = { 2, 3 };
Console.WriteLine( arr1.Intersect(arr2).SequenceEqual(arr2)); // will return true
For the case <= ({ "E", "E" } is true) it is quite simple:
static List<string> list1 = new List<string> { "E", "C", "B", "A" };
// Uses a <= algorithm, so "E", "E" is true
public static bool IsSorted(IEnumerable<string> enu)
{
// index of last letter used in list1
int lastIndex = 0;
foreach (string str in enu)
{
// Start searching from the last index found
int index = list1.IndexOf(str, lastIndex);
// index == -1 means not found
if (index == -1)
{
return false;
}
lastIndex = index;
}
return true;
}
Comments in code.
if you want a <, so that { "E", "E" } is false:
// Uses a < algorithm, so "E", "E" is false
public static bool IsSorted(IEnumerable<string> enu)
{
// Note that we have a +1 in the IndexOf to balance the -1 here
int lastIndex = -1;
foreach (string str in enu)
{
// Start searching from the last index found + 1
int index = list1.IndexOf(str, lastIndex + 1);
// index == -1 means not found
if (index == -1)
{
return false;
}
lastIndex = index;
}
return true;
}
You can use two LINQ methods for that: Intersect to get the items that are common to both lists; and then SequenceEqual to check if both lists have the same items in the same order. So:
listToCheck.Intersect(list1).SequenceEqual(listToCheck)

find the two longest word made of other words

I want to find two longest words from array ,made from smaller words. my code are given below.
current out put is:
catxdogcatsrat, ratcatdogcat, catsdogcats, dogcatsdog
required output is:
ratcatdogcat, catsdogcats
class program
{
public static void Main(String[] args)
{
List<string> list2 = new List<string>();
string[] stringrray = { "cat", "cats", "catsdogcats", "catxdogcatsrat", "dog", "dogcatsdog",
"hippopotamuses", "rat", "ratcatdogcat" };
list2.Add(stringrray[0]);
list2.Add(stringrray[1]);
list2.Add(stringrray[2]);
list2.Add(stringrray[3]);
list2.Add(stringrray[4]);
list2.Add(stringrray[5]);
list2.Add(stringrray[6]);
list2.Add(stringrray[7]);
list2.Add(stringrray[8]);
List<string> list = new List<string>();
var mod = list2.OrderByDescending(x => x.Length).ToList();
int j = 1;
for (int k = 0; k < mod.Count; k++)
{
for (int i = 0; i < mod.Count-j; i++)
{
if (mod[i].Contains(mod[mod.Count - j]))
{
j++;
list.Add(mod[i]);
}
}
}
var mod1 = list.OrderByDescending(x => x.Length);
foreach (var i in mod1)
{
Console.WriteLine(i);
}
Console.ReadLine();
}
}
I think you are looking for something like this
string[] stringrray = { "cat", "cats", "catsdogcats", "catxdogcatsrat", "dog", "dogcatsdog", "hippopotamuses", "rat", "ratcatdogcat" };
List<string> list2 = new List<string>(stringrray);
List<string> Finallist = new List<string>();
char[] smallstrchar = String.Join("", list2.Where(x => x.Length <= 4)).ToCharArray();
char[] bigstrchar = String.Join("", list2.Where(x => x.Length > 4)).ToCharArray();
char[] modchar = bigstrchar.Except(smallstrchar).ToArray();
foreach(string bigstr in list2)
{
if(!(bigstr.IndexOfAny(modchar) != -1))
{
Finallist.Add(bigstr);
}
}
Finallist = Finallist.OrderByDescending(x => x.Length).Take(2).ToList();
foreach(string finalstr in Finallist)
{
Console.WriteLine(finalstr);
}
So first is the stringrray which contains all the strings which are supposed to be taken care and find the longest one out of it. With your code it also takes the string which contains x in them but all other chars are matched. So I have made a list of strings in list2 which contains all the values. Then splitted the list2 in 2 parts that is smallstrchar array contains all the chars of the smaller strings less than length of 4 and Bigstrchar contains all chars of strings which are bigger than length of 5. Now Except takes out all the chars which does not exsist in the smallstrchar and present in Bigstrchar. Now we have the list of chars which need to be excluded from the sort.
Finally IndexOfAny to find in that string contains that char or not. If not then add to Finallist. Later we can take 2 from the list.
Hope this helps
You could simplify adding the array to list2 with
list2.AddRange(stringrray)
You may use this code...
static void Main(string[] args)
{
List<string> words = new List<string>() { "cat", "cats", "catsdogcats", "catxdogcatsrat", "dog", "dogcatsdog", "hippopotamuses", "rat", "ratcatdogcat" };
List<string> result = new List<string>();
// solution 1
foreach (string word in words)
{
if (IsCombinationOf(word, words))
{
result.Add(word);
}
}
// solution 2
result = words.Where(x => IsCombinationOf(x, words)).ToList();
}
public static bool IsCombinationOf(string word, List<string> parts)
{
// removing the actual word just to be secure.
parts = parts.Where(x => x != word).OrderByDescending(x => x.Length).ToList();
// erase each part in word. Only those which are not in the list will remain.
foreach (string part in parts)
{
word = Regex.Replace(word, part, "");
}
// if there are any caracters left, it hasn't been a combination
return word.Length == 0;
}
but...
This code has a little bug. The OrderbyDescending clause ensures that cats will be removed before cat. Otherwise the s would remain and the code wouldn't work as expected. But if we use some fictional values this code will not work properly. For example:
List<string> words = new List<string>() { "abz", "e", "zefg", "f", "g", "abzefg" };
Let's have a look at abzef. The algorithm will remove zefg first, but then it's not possible to go any futher. Indeed, the word is a combination of abz, e, f and g .

C# : How to get running combination from two List<String> based on a master list

Dear all , this is something like my previous question How to get moving combination from two List<String> in C#?
I'm having a masterlist and two childlist like below
List<String> MasterList = new List<string> { "A", "B", "C", "D", "E" };
List<String> ListOne = new List<string> { "A", "B", "C" };
List<String> ListTwo = new List<String> { "B", "D" };
I just need to get the running combination from the above list for that i'm using like(previous question's answer(Thanks Danny Chen))
List<String> Result = new List<string>();
Result = ListOne.SelectMany((a, indexA) => ListTwo
.Where((b, indexB) => ListTwo
.Contains(a) ? !b.Equals(a) && indexB > indexA :
!b.Equals(a)).Select(b => string.Format("{0}-{1}", a, b))).ToList();
so the Result list will contain
"A-B"
"A-D"
"B-D"
"C-B"
"C-D"
Now my problem is the sorting issue
In the above result the fourth entry is C-B but it should be B-C. Because in the MasterList the C is after B.
How to do this in my existing linq .
Please help me to do this.
Not really clear on the exact requirement here, so does the MasterList dictate which of the two items should appear first? What about the order of the X1-X2 list? i.e. should B-C appear before B-D because C appears before D in the MasterList?
Anyway, here's something that produces the result you've asked for so far:
List<String> MasterList = new List<string> { "A", "B", "C", "D", "E" };
List<String> ListOne = new List<string> { "A", "B", "C" };
List<String> ListTwo = new List<String> { "B", "D" };
ListOne.SelectMany(i =>
ListTwo.Where(i2 => i != i2)
.Select(i2 =>
{
if (MasterList.IndexOf(i) < MasterList.IndexOf(i2))
return string.Format("{0}-{1}", i, i2);
else
return string.Format("{0}-{1}", i2, i);
}
));
outputs:
A-B
A-D
B-D
B-C
C-D

Categories

Resources