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.
Related
There are two sets of:
int Transformer substations
object Buildings(the set is larger than the first set at least by 5 times).
The building has 2 parameters (number and load).
Need to create all possible combinations: each transformer station is loaded by 60-80% in every combination, and buildings don't repeat.
Glad to hear any suggestions.
Tried the Cartesian product but I have no idea how to apply it. Ideas just don't appear. I guess it is because of the stress produced by the war in Ukraine where I live.
A cartesian product without elements repetition in any given result set and without permutations:
static void combinations(List<List<string>> srs, int[] size, List<string> curr, int index)
{
if (index == srs.Count())
{
int s = curr.Count();
string[] d = new string[s];
List<string> x = d.ToList();
x.AddRange(curr);
x.RemoveAll(item => item == null);
dest.Add(x);
string res = "";
foreach (var item in x)
{
res += item + ", ";
}
//dest.add(d);
Console.WriteLine(res);
}
else
{
for (int i = 0; i < size[index]; i++)
{
int n = size[index];
string[] dim = new string[n];
dim = srs[index].ToArray();
curr.Add(dim[i]);
index++;
combinations(srs, size, curr, index);
index--;
curr.RemoveAt(curr.Count() - 1);
}
}
}
public static void init()
{
string[] confidence = new string[] { "High", "Low Variable" };
string[] goalspec = new string[] { "High", "Low Some" };
string[] quality = new string[] { "High", "Low Variable" };
string[] tansSkills = new string[] { "High", "Low some" };
string[] sitLead = new string[] { "S1", "S2", "S3", "S4" };
string[] devLev = new string[] { "D1", "D2", "D3", "D4" };
string[] statReason = new string[] {"In backlog", "Canceled", "Completed" };
List<List<string>> srs = new List<List<string>>
{
confidence.ToList(),
goalspec.ToList(),
quality.ToList(),
tansSkills.ToList(),
sitLead.ToList(),
devLev.ToList(),
statReason.ToList()
};
number_elem = srs.Count();
int[] size = new int[number_elem];
size[0] = confidence.Count();
size[1] = goalspec.Count();
size[2] = quality.Count();
size[3] = tansSkills.Count();
size[4] = sitLead.Count();
size[5] = devLev.Count();
size[6] = statReason.Count();
dest = new List<List<string>>();
List<string> curr = new List<string>();
combinations(srs, size, curr, 0);
}
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
}
}
}
}
I have three string arrays
string[] stringArray= {"AAA", "BBB", "CCC","DDD", "EEE","FFF","GGG","HHH" };
string[] stringArray1 = { "A", "B", "C","D", "E","F","G","H" };
string[] stringArray2 = { "BBB", "DDD","FFF","HHH" };
How could I compare stringArray2 with stringArray and find the index number stringArray that matches.
After finding the index ,I need to apply it to stringArray1
and display the results.
I have tried the following code ,but failed to get the match string
int j=0;
string line = null;
List<string> finalstring = new List<string>();
for (int i = 0; i < stringArray.Count; i++)
{
while(stringArray[i] == stringArray2[j])
{
line = stringArray2[i];
finalstring.Add(line);
j++;
}
}
I think you have to try like this:
var result = stringArray1.Where(c => // iterating stringArray1
stringArray2.Where(x => stringArray.Contains(x)) // filtering stringArray2 elements
.Any(y=>y.Contains(c))).ToList(); // collect the final result
A Working example for your reference
int j=0;
string line = null;
List<string> finalstring = new List<string>();
for (int i = 0; i < stringArray.Length; i++)
//for (int i = 0; i < stringArray.Count; i++) // <-- Count is not proper way to get total elements in an array
{
j = 0; // <-- you failed to reinitialize 'j'
//while(stringArray[i] == stringArray2[j]) // <-- while is not proper way to compare
if(stringArray[i] == stringArray2[j])
{
//line = stringArray2[i];
//if only first charracter is needed
finalstring.Add(new string(stringArray2[i][0], 1));
//if complete string is needed
//finalstring.Add(stringArray2[i]);
j++;
}
}
Above is not an optimized way to do the comparisons. You can try using HashSet class
string[] stringArray= {"AAA", "BBB", "CCC","DDD", "EEE","FFF","GGG","HHH" };
string[] stringArray1 = { "A", "B", "C","D", "E","F","G","H" };
string[] stringArray2 = { "BBB", "DDD","FFF","HHH" };
//convert string array to hashset
var hashSet = new HashSet<string>(stringArray);
int j=0;
string line = null;
List<string> finalstring = new List<string>();
for (int i = 0; i < stringArray2.Length; i++)
{
if(hashSet.Contains(stringArray2[i]))
{
//if only first charracter is needed
finalstring.Add(new string(stringArray2[i][0], 1));
}
}
List<string> finalList = new List<string>();
stringArray.Select((value,index) => new { value, index })
.Where(num => stringArray2.Contains(num.value)).ToList()
.ForEach(num => finalList.Add(stringArray1[num.index]));
you could do it with selecting the index via Linq (where >= 0 filters out all non matches):
string[] stringArray = { "AAA", "BBB", "CCC", "DDD", "EEE", "FFF", "GGG", "HHH" };
string[] stringArray1 = { "A", "B", "C", "D", "E", "F", "G", "H" };
string[] stringArray2 = { "BBB", "DDD", "FFF", "HHH" };
var matches = stringArray2
.Select(s => Array.FindIndex(stringArray, s2 => s2 == s))
.Where(i => i >= 0).Select(i => stringArray1[i])
.ToList();
Here a dotnetfiddle
You are trying to compare the elements on same index but you have to search the element of stringArray2 in stringArray. You can use Array.IndexOf to find in Array the required element.
string[] stringArray= {"AAA", "BBB", "CCC","DDD", "EEE","FFF","GGG","HHH" };
string[] stringArray1 = { "A", "B", "C","D", "E","F","G","H" };
string[] stringArray2 = { "BBB", "DDD","FFF","HHH" };
int j=0;
string line = null;
List<string> finalstring = new List<string>();
for (int i = 0; i < stringArray2.Count(); i++)
{
if(Array.IndexOf(stringArray, stringArray2[i]) != -1)
{
int idx = Array.IndexOf(stringArray1, stringArray2[i][0].ToString());
if(idx!=-1)
finalstring.Add(stringArray1[idx]);
}
}
Edit using Linq
var result2 = stringArray1.Where(c=>
stringArray2.Intersect(stringArray)
.Any(i=>i.Contains(c)));
I am looking to find the differences between two Lists of string arrays using the index 0 of the array as the primary key.
List<string[]> original = new List<string[]>();
List<string[]> web = new List<string[]>();
//define arrays for List 'original'
string[] original_a1 = new string[3]{"a","2","3"};
string[] original_a2 = new string[3]{"x","2","3"};
string[] original_a3 = new string[3]{"c","2","3"};
//define arrays for List 'web'
string[] web_a1 = new string[3]{"a","2","3"};
string[] web_a2 = new string[3]{"b","2","3"};
string[] web_a3 = new string[3]{"c","2","3"};
//populate Lists
original.Add(original_a1);
original.Add(original_a2);
original.Add(original_a3);
web.Add(web_a1);
web.Add(web_a2);
web.Add(web_a3);
My goal is to find what is in List 'original' but NOT in 'web' by using index 0 as the primary key
This is what I tried.
List<string> differences = new List<string>(); //differences go in here
string tempDiff = ""; // I use this to try and avoid duplicate entries but its not working
for(int i = 0; i < original.Count; i++){
for(int j = 0; j< web.Count; j++){
if(!(original[i][0].Equals(web[j][0]))){
tempDiff = original[i][0];
}
}
differences.Add(tempDiff);
}
OUTPUT:
foreach(string x in differences){
Console.WriteLine("SIZE " + differences.Count);
Console.WriteLine(x);
ConSole.ReadLine();
}
SIZE 3
SIZE 3
x
SIZE 3
x
Why is it reporting the mismatch 3 times instead of once?
Using linq you can just go:
var differences = orignal.Except(web).ToList();
Reference here
This will give you the values that are in original, that don't exist in web
Sorry didn't read your question properly, to answer your question:
You have a nested for-loop. So for each value of original (3) it will loop through all values of web (3), which is 9 loops total.
In 3 cases it doesn't match and therefore outputs 3 times.
I think this is what you want. I use Linq to grab the primary keys, and then I use Except to do original - web. By the way, you can use == instead of Equals with strings in C# because C# does a value comparison as opposed to a reference comparison.
List<string[]> original = new List<string[]>
{
new string[3] { "a", "2", "3" },
new string[3] { "x", "2", "3" },
new string[3] { "c", "2", "3" }
};
List<string[]> web = new List<string[]>
{
new string[3] { "a", "2", "3" },
new string[3] { "b", "2", "3" },
new string[3] { "c", "2", "3" }
};
var originalPrimaryKeys = original.Select(o => o[0]);
var webPrimaryKeys = web.Select(o => o[0]);
List<string> differences = originalPrimaryKeys.Except(webPrimaryKeys).ToList();
Console.WriteLine("The number of differences is {0}", differences.Count);
foreach (string diff in differences)
{
Console.WriteLine(diff);
}
And here it is without Linq:
var differences = new List<string>();
for (int i = 0; i < original.Count; i++)
{
bool found = false;
for (int j = 0; j < web.Count; j++)
{
if (original[i][0] == web[j][0])
{
found = true;
}
}
if (!found)
{
differences.Add(original[i][0]);
}
}
To answer your question: It is a nested for loop as stated in JanR's answer. This approach will make you reiterate to your web count 9 times, thus listing your mismatched key three times.
What could be a better way to do is this:
//Check for originals not introduced in web.
if(original.Count > web.Count)
{
for(int y = web.Count; y < original.Count; y++)
{
differences.Add(original[y][0]);
}
}
//Check if Web has value, if not, everything else is done on the first for loop
if(web.Count > 0)
{
for(int i = 0; i < original.Count; i++)
{
if(!original[i][0].Equals(web[i][0]))
differences.Add(original[i][0]);
}
}
Also, the output is in a for loop, when you just need one result, the length of the mismatch. You can do that without a loop.
Console.WriteLine("SIZE " + differences.Count);
This is, of course to make it kinda simpler if you're not used to using LINQ statements, but if you can do so with LINQ, then by all means, use LINQ as it's more efficient.
You can get the difference by using Except extension method like this:
var originalDic = original.ToDictionary(arr => arr.First());
var webDic = web.ToDictionary(arr => arr.First());
var differences =
originalDic
.Except(webDic, kvp => kvp.Key)
.Select(kvp => kvp.Value)
.ToList();
The trick here is to first convert your original and web lists into a Dictionary using the first element of each array as key and then perform Except.
First of all sorry for my mistakes in English its not my primary language
i have a problem , i have a array like following
string[] arr1 = new string[] {
"Pakistan:4,India:3,USA:2,Iran:1,UK:0",
"Pakistan:4,India:3,USA:2,Iran:1,UK:0",
"India:4,USA:3,Iran:2,UK:1,Pakistan:0"
};
now i just want to know that how many times Pakistan comes with 1 ,
how many times with 2 , 3 , 4
and i need to know this about all India , USA , Iran , UK
Thanks in advance , you guys are my last hope .
This linq will convert the array into a Dictionary>, where the outer dictionary contains the countries names, and inner dictionaries will contain the ocurrence number (the number after ':') and the count for each ocurrence.
string[] arr1 = new string[]
{
"Pakistan:4,India:3,USA:2,Iran:1,UK:0",
"Pakistan:4,India:3,USA:2,Iran:1,UK:0",
"India:4,USA:3,Iran:2,UK:1,Pakistan:0"
};
var count = arr1
.SelectMany(s => s.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
.GroupBy(s => s.Split(':')[0], s => s.Split(':')[1])
.ToDictionary(g => g.Key,
g =>
{
var items = g.Distinct();
var result = new Dictionary<String, int>();
foreach (var item in items)
result[item] = g.Count(gitem => gitem == item);
return result;
});
// print the result
foreach(var country in count.Keys)
{
foreach(var ocurrence in count[country].Keys)
{
Console.WriteLine("{0} : {1} = {2}", country, ocurrence, count[country][ocurrence]);
}
}
I would use the String.Split(char[]) method and the String.SubString(int, int) method to inspect every 'country' inside your array and to get the number postfix of each country.
Try the following:
(The following code is now compiled and tested.)
Use a simple data structure to facilitate the task of holding the result of your operation.
public struct Result {
string Country { get; set; }
int Number { get; set; }
int Occurrences { get; set; }
}
// define what countries you are dealing with
string[] countries = new string[] { "Pakistan", "India", "USA", "Iran", "UK", }
Method to provide the overall result:
public static Result[] IterateOverAllCountries () {
// range of numbers forming the postfix of your country strings
int numbersToLookFor = 4;
// provide an array that stores all the local results
// numbersToLookFor + 1 to respect that numbers are starting with 0
Result[] result = new Result[countries.Length * (numbersToLookFor + 1)];
string currentCountry;
int c = 0;
// iterate over all countries
for (int i = 0; i < countries.Length; i++) {
currentCountry = countries[i];
int j = 0;
// do that for every number beginning with 0
// (according to your question)
int localResult;
while (j <= numbersToLookFor) {
localResult = FindCountryPosition(currentCountry, j);
// add another result to the array of all results
result[c] = new Result() { Country = currentCountry, Number = j, Occurrences = localResult };
j++;
c++;
}
}
return result;
}
Method to provide a local result:
// iterate over the whole array and search the
// occurrences of one particular country with one postfix number
public static int FindCountryPosition (string country, int number) {
int result = 0;
string[] subArray;
for (int i = 0; i < arr1.Length; i++) {
subArray = arr1[i].Split(',');
string current;
for (int j = 0; j < subArray.Length; j++) {
current = subArray[j];
if (
current.Equals(country + ":" + number) &&
current.Substring(current.Length - 1, 1).Equals(number + "")
)
result++;
}
}
return result;
}
The following should enable you to run the algorithm
// define what countries you are dealing with
static string[] countries = new string[] { "Pakistan", "India", "USA", "Iran", "UK", };
static string[] arr1 = new string[] {
"Pakistan:4,India:3,USA:2,Iran:1,UK:0",
"Pakistan:4,India:3,USA:2,Iran:1,UK:0",
"India:4,USA:3,Iran:2,UK:1,Pakistan:0"
};
static void Main (string[] args) {
Result[] r = IterateOverAllCountries();
}
The data structure you are using is not rich enough to provide you with that information. Hence you need to parse your string and create a new data structure to be able to provide (sring[][]):
string[] arr1 = new string[] {
"Pakistan,India,USA,Iran,UK",
"Pakistan,India,USA,Iran,UK",
"India,USA,Iran,UK,Pakistan"
};
string[][] richerArray = arr1.Select(x=> x.Split('\'')).ToArray();
var countPakistanIsFirst = richerArray.Select(x=>x[0] == "Pakistan").Count();
UPDATE
You seem to have changed your question. The answer applies to the original question.