Looping through multi dimensional array - c#

Edit
The approach taken here was completely wrong. This is how it should have been done.
public class Recipe {
public List<string> ingredients;
public string result;
public Recipe (List<string> _ingredients, string _result) {
this.ingredients _ingredients;
this.result = _result;
}
}
And then when looping:
Recipe[] recipes = new Recipe[] {
new Recipe(new List<string>(new string[] { "potato", "tabasco" }), "explosivePotato"),
new Recipe(new List<string>(new string[] { "mentos", "cola" }), "colaCannon"),
new Recipe(new List<string>(new string[] { "potato", "cola" }), "potatoCola"),
new Recipe(new List<string>(new string[] { "potato", "chips" }), "potatoChips")
}
This would also mean that looping would be a whole lot simpler.
Original question
I have a C# script with the following array:
string[,] craftingRecipes = new string[,]{
// {recipe},{result}
{"potato","tabasco"},{"explosivePotato"},
{"mentos","cola"},{"colaCannon"},
{"potato","cola"},{"potatoCola"},
{"potato","chips"},{"potatoChips"}
};
How can i loop through every item in the n'th subarray? So for example the array containing {"potato","tabasco"} should be looped twice, since there are two items in it.
Thank you for any help!

I'm not sure I understood your question, since your code doesn't compile, but you can use this loop to iterate through items in first "line":
int line = 0;
for (int i = 0; i < craftingRecipes.GetLength(1); i++)
{
Console.WriteLine(craftingRecipes[line,i]);
}
Although, Your array should look more like this (I had to add sth_missing_here, because Multi-Dimensional Array must have sub-arrays with the same length):
string[,] craftingRecipes = new string[,]{
{"potato","tabasco"},{"explosivePotato","sth_missing_here_1"},
{"mentos","cola"},{"colaCannon","sth_missing_here_2"},
{"potato","cola"},{"potatoCola","sth_missing_here_3"},
{"potato","chips"},{"potatoChips","sth_missing_here_3"}
};

You can use the OfType<T> method, to convert the multidimensional array into an IEnumerable<T> result, for sample:
IEnumerable<string> items = craftingRecipes.OfType<int>();
foreach(var item in items)
{
// loop between all elements...
}

As per the edit 19-09-2018, this can now be properly answered.
Iterate over the array using two simple nested foreach loops.
foreach (Recipe recipe in recipes) {
System.Console.Write("To make '{0}' you need:", recipe.result);
foreach (ingredient in recipe.ingredients) {
System.Console.Write(ingredient);
}
}

Related

Sorting One list alphabetically and having the other 3 list be re sorted in the same order [duplicate]

This question already has answers here:
Sorting two separate Lists in the same order?
(4 answers)
How do I sort 2 lists by the same criteria?
(2 answers)
Sort two Lists<T> together as one?
(7 answers)
Identically sorting two lists
(4 answers)
Sort Two Lists with relationship
(1 answer)
Closed 3 years ago.
List<string> listOfStudentsNames = new List<string>();
List<string> listOfStudentsHomeTown = new List<string>();
List<string> listOfStudentsFavoriteFood = new List<string>();
List<string> listOfStudentsFavoriteColor = new List<string>();
So in the mini app the user enters the students name, followed by hometown, favorite food, and favorite color. So my goal at any time once the user adds a new student the names in the list are put in alphabetical order. Which that I can get to work just fine I know how to get the list in alphabetical order. My issue is I need to get the other 3 list hometown, favorite food, and color to be resorted according to how the name list was sorted (aka so the students names still re align to what their hometown favorite food and color is). I'm having trouble coming up with the logic to do this..
This is how I have the sorting list alphabetically function set up.
Right now it's only sorting the names with the issue being how i sort the other three lists to how names was sorted alphabetically
public static void SortListAlphabetically
(List<string> listOfstudentsNames,
List<string> listOfStudentsFavoriteFoods,
List<string> listOfStudentsHomeTown,
List<string> listOfStudentsFavoriteColor)
{
List<string> unSortedList = new List<string>(listOfstudentsNames);
List<string> tempListOfStudentsFood = new List<string>(listOfStudentsFavoriteFoods);
List<string> tempListHomeTown = new List<string>(listOfStudentsHomeTown);
List<string> tempListFavColor = new List<string>(listOfStudentsFavoriteColor);
unSortedList.Sort();
for (int i = 0; i < unSortedList.Count; i++)
{
listOfstudentsNames[i] = unSortedList[i];
}
}
This may solve your question. I don't know if you are adding the names and you wanna keep order or if you have already the names and you wanna sort all at the end keeping the match between the name index and the other info index. I code the two variants:
Way 1 (Adding the names keeping order):
I made a BinaryInsert method that inserts the name in the correct position using binary search (this is very fast) and then it returns the position it inserted the name. This will be the position where you most insert the other info.
static void Main(string[] args)
{
AddStudent("Mike", "home1", "food1", "color1");
AddStudent("Pete", "home2", "food2", "color2");
AddStudent("Andrea", "home3", "food3", "color3");
AddStudent("Zoey", "home4", "food4", "color4");
AddStudent("Tom", "home5", "food5", "color5");
}
static List<string> listOfStudentsNames = new List<string>();
static List<string> listOfStudentsHomeTown = new List<string>();
static List<string> listOfStudentsFavoriteFood = new List<string>();
static List<string> listOfStudentsFavoriteColor = new List<string>();
public static void AddStudent(string name, string homeTown, string favFood, string favColor)
{
int namePos = BinaryInsert(listOfStudentsNames, name);
listOfStudentsHomeTown.Insert(namePos, homeTown);
listOfStudentsFavoriteFood.Insert(namePos, favFood);
listOfStudentsFavoriteColor.Insert(namePos, favColor);
}
public static int BinaryInsert<T>(List<T> elements, T item) where T : IComparable
{
return BinaryInsertRescursive(elements, item, 0, elements.Count);
}
private static int BinaryInsertRescursive<T>(List<T> elements, T item, int startIndex, int finishIndex) where T : IComparable
{
if (startIndex == finishIndex)
{
elements.Insert(startIndex, item);
return startIndex;
}
int pos = startIndex + (finishIndex - startIndex) / 2;
if (item.CompareTo(elements[pos]) <= 0)
finishIndex = pos;
else
startIndex = pos + 1;
return BinaryInsertRescursive(elements, item, startIndex, finishIndex);
}
Way 2 (Sorting all at the end and keep the match between names index and other info index):
static void Main(string[] args)
{
//Assuming these are the names that where added with their info
listOfStudentsNames = new List<string>() { "Tom", "Andrea", "Zoey", "Mike", "Pete" };
listOfStudentsHomeTown = new List<string>() { "home1", "home2", "home3", "home4", "home5" };
listOfStudentsFavoriteFood = new List<string>() { "food1", "food2", "food3", "food4", "food5" };
listOfStudentsFavoriteColor = new List<string>() { "color1", "color2", "color3", "color4", "color5" };
Sort(listOfStudentsNames,
listOfStudentsHomeTown,
listOfStudentsFavoriteFood,
listOfStudentsFavoriteColor);
}
static List<string> listOfStudentsNames = new List<string>();
static List<string> listOfStudentsHomeTown = new List<string>();
static List<string> listOfStudentsFavoriteFood = new List<string>();
static List<string> listOfStudentsFavoriteColor = new List<string>();
public static void Sort(List<string> names, params List<string>[] otherInfo)
{
// I use params for the other info because you will be able
// to add more info-lists without making any changes to this code
// save the index of each name
var nameWithIndexes = names.Select(x => new Tuple<string, int>(x, names.IndexOf(x))).ToList();
//sort the list by the names
nameWithIndexes.Sort((x, y) => x.Item1.CompareTo(y.Item1));
names.Clear();
names.AddRange(nameWithIndexes.Select(x => x.Item1));
// get de index of the names afert sorting
var order = nameWithIndexes.Select(x => x.Item2);
// sort the other info by the index order int the variable "order"
for (int i = 0; i < otherInfo.Length; i++)
{
var newOrder = new List<string>();
foreach (var index in order)
{
newOrder.Add(otherInfo[i][index]);
}
otherInfo[i].Clear();
otherInfo[i].AddRange(newOrder);
}
}
I hope this could help.

c# Get only numbers from list of strings which contain numbers and words

I have a list of strings (word--number) ex (burger 5$). I need to extract only numbers from every string in list and make new int list.
There are several ways to do that, Regex and Linq for example.
For short string you can use Linq, for example:
public static void Main()
{
var myStringValue = "burger 5$";
var numbersArray = myStringValue.ToArray().Where(x => char.IsDigit(x));
foreach (var number in numbersArray)
{
Console.WriteLine(numbersArray);
}
}
If you take a look at the Regex.Split, numbers article.
You'll find the answer in there. Modified code might look like
var source = new List<string> {
"burger 5$",
"pizza 6$",
"roll 1$ and salami 2$"
};
var result = new List<int>();
foreach (var input in source)
{
var numbers = Regex.Split(input, #"\D+");
foreach (string number in numbers)
{
if (Int32.TryParse(number, out int value))
{
result.Add(value);
}
}
}
Hope it helps.
Petr
Using linq and Regex:
List<string> list = new List<string>(){"burger 5$","ab12c","12sc34","sd3d5"};
Regex nonDigits = new Regex(#"[^\d]");
List<string> list2 = list.Select(l => nonDigits.Replace(l, "")).ToList();
You can take a look and also solve the problem with this code:
List<string> word_number = new List<string>();
List<int> number = new List<int>();
word_number.Add("burger 5$");
word_number.Add("hamburger 6$");
word_number.Add("burger 12$");
foreach (var item in word_number)
{
string[] parts = item.Split(' ');
string[] string_number = parts[1].Split('$');
number.Add(Convert.ToInt16(string_number[0]));
Console.WriteLine(string_number[0]);
}

Trying to sort a list full of a object by the a list from that object's properties c#

I have a class that has a bunch of different variables and a couple lists 1 in particular holds ints(positionInts)
I also have a list(teamsList) for holding objects I have created from that class
now I would like to sort the team's list by positions values
Hopefully, I'm not being too vague as the project I'm working on is full of not well-written code so it can be hard to explain.
This function orders the list according to your precondition.
private List<String> OrderList(List<String> teams, int[] positions)
{
List<String> orderedTeams;
Dictionary<int, string> teamsToOrder = new Dictionary<int, string>();
int position = 0;
foreach (string team in teams)
{
teamsToOrder.Add(positions[position], teams[position]);
position = position + 1;
}
orderedTeams = teamsToOrder.OrderByDescending(team => team.Key).Select(team => team.Value).ToList();
return orderedTeams;
}
If I understand your question correctly, then you have list of arbitrary type, for example list of strings:
var teamsList = new List<String> { "team1", "team2", "team3", "team4" };
Next up, you have enumeration of integers:
var positionInts = new[] { 2, 3, 1, 0 };
And your goal is to order teamsList based on sequence numbers of the positionInts. In that case you can use following method:
static IEnumerable<T> OrderBySequence<T>(IEnumerable<T> source, IEnumerable<Int32> sequence)
{
for (var i = 0; i < Math.Min(source.Count(), sequence.Count()); i++)
{
var s = sequence.ElementAt(i);
if (s > -1 && s < source.Count())
{
yield return source.ElementAt(s);
}
}
}
Which will produce:
team3
team4
team2
team1

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 .

Checking the equality of lists in foreach loop - C#

I'm trying to check the equality of 2 lists of string but it's not working. This is what I have done:
foreach (List<string> q in questions)
{
if (!groupOfQuestions.Except(q).Any()) //I also tried without '!'
{
questions.Add(groupOfQuestions);
}
}
And declaration of lists:
List<List<string>> questions = new List<List<string>>();
List<string> groupOfQuestions = new List<string>();
You can't modify collection within foreach loop, but you can do it in for loop:
for (int i = questions.Count - 1; i >= 0; --i) {
List<string> q = questions[i];
if (!groupOfQuestions.Except(q).Any()) //I also tried without '!'
questions.Add(groupOfQuestions);
}
Another possibility is to loop on collection's copy:
// Note ".ToList()"
foreach (List<string> q in questions.ToList())
if (!groupOfQuestions.Except(q).Any()) //I also tried without '!'
questions.Add(groupOfQuestions);
Your problem is on this line:
questions.Add(groupOfQuestions);
You cannot modify a collection while you are iterating over it.
You're going to need to create a new List<List<string>> that you can add the matches to. For example:
var questions = new List<List<string>> {
new List<string>{"aaa", "bbb", "ccc"},
new List<string>{"aaa", "bbb", "ddd"},
};
var groupOfQuestions = new List<string>() { "ddd" };
var questionMatches = new List<List<string>>();
foreach (List<string> q in questions)
{
if (!groupOfQuestions.Except(q).Any()) //I also tried without '!'
{
questionMatches.Add(groupOfQuestions);
}
}
questions can not be modified when iterating over it in a foreach. Build a new list and run AddRange at the end:
var listsToAdd = new List<List<string>>();
foreach (List<string> q in questions)
{
if (!groupOfQuestions.Except(q).Any())
{
questions.Add(groupOfQuestions);
}
}
questions.AddRange(listsToAdd);

Categories

Resources