3 Arrays into 1 Array with all Combinations (code inside) - c#

I have the following code:
static void Main(string[] args)
{
string[] h = new string[2];
h[0] = "h0";
h[1] = "h1";
string[] d = new string[2];
d[0] = "d0";
d[1] = "d1";
string[] a = new string[2];
a[0] = "a0";
a[1] = "a1";
}
What would be the code to generate an array containing each of the following items:
h0h1,h0d1,h0a1,d0h1,d0d1,d0a1,a0h1,a0d1,a0a1
I have been trying with nested for loops, but can't get the list of combinations above.

Dim list as New List<string[]>
Dim result = new string[N] /* N in this case will be 9 (3^2) */
list.Add(h)
list.Add(d)
list.Add(a)
for(int i =0; i< N; i++)
{
result[i] = list[Math.Truncate(i/3)][0] + list[i%3][1]
}
I think it's clear enough, I will extend if needed, for now:
list[Math.Truncate(i/3)][0]: we get the array in the list
(1st one for i:0..2, 2nd one for i:3..5 and 3nd one for i:6..8)
and we get its first item ([0]) value
list[i%3][1]: we get the array in the list (1st one for i:0,3,6; 2nd one for i:1,4,7; and 3nd one for i:2,5,8) and we get its second ([1]) item's value
Then just concatenate both ítems and store them in their index

Related

Create two random lists from one list

I want to take a List of strings with around 12 objects and split it into two List of strings but completely randomise it.
Example of List:
List 1:
EXAMPLE 1
EXAMPLE 2
EXAMPLE 3
EXAMPLE 4
EXAMPLE 5
EXAMPLE 6
EXAMPLE 7
EXAMPLE 8
Apply some logic here...
Result gives me two lists:
List 1:
EXAMPLE 5
EXAMPLE 6
EXAMPLE 1
EXAMPLE 8
List 2:
EXAMPLE 2
EXAMPLE 3
EXAMPLE 4
EXAMPLE 7
I'm a newbie to C# MVC, so I've found some answers on Stack but none have been able to answer my question.
Edit:
What I've tried so far gives me one random member of the team. I want to now expand on this and create the two lists as mentioned above.
[HttpPost]
public ActionResult Result(Models.TeamGenerator model)
{
var FormNames = model.Names;
string[] lines = FormNames.Split(
new[] { Environment.NewLine },
StringSplitOptions.None);
List<string> listOfLines = new List<string>();
foreach (var i in lines)
{
listOfLines.Add(i);
}
string[] result1 = listOfLines.Where(item => item != string.Empty).ToArray();
Random genRandoms = new Random();
int aRandomTeam = genRandoms.Next(listOfLines.Count);
string currName = listOfLines[aRandomTeam];
return View();
}
*EDIT** Thanks for the solution! I've now got my application working and managed to publish it to the web, https://www.teamgenerator.online.
Create an array of bools the same size as the list of strings.
Fill one half of the array of bools with true, the other half with false.
Shuffle the array of bools.
Iterate through the list of strings. For each element, if the corresponding element in the bool array is true, include that element in the first list; otherwise include it in the second list.
This approach keeps the items in the same order as they were in the original array, if that is important. (If not, just shuffle the entire array of strings and take the first half and the second half).
Sample code:
using System;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
public static void Main()
{
var strings = Enumerable.Range(1, 20).Select(i => i.ToString()).ToList();
var rng = new Random();
int n = strings.Count;
var include = // Create array of bools where half the elements are true and half are false
Enumerable.Repeat(true, n/2) // First half is true
.Concat(Enumerable.Repeat(false, n-n/2)) // Second half is false
.OrderBy(_ => rng.Next()) // Shuffle
.ToArray();
var list1 = strings.Where((s, i) => include[i]).ToList(); // Take elements where `include[index]` is true
var list2 = strings.Where((s, i) => !include[i]).ToList(); // Take elements where `include[index]` is false
Console.WriteLine(string.Join(", ", list1));
Console.WriteLine(string.Join(", ", list2));
}
}
}
Here's a completely different approach that uses a modified version of a standard algorithm for selecting K items from N items (in this case, K = N/2):
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
public static void Main()
{
var strings = Enumerable.Range(1, 20).Select(n => n.ToString()).ToList();
var list1 = new List<string>();
var list2 = new List<string>();
var rng = new Random();
int available = strings.Count;
int remaining = available / 2;
foreach (var s in strings)
{
if (rng.NextDouble() < remaining / (double) available)
{
list1.Add(s);
--remaining;
}
else
{
list2.Add(s);
}
--available;
}
Console.WriteLine(string.Join(", ", list1));
Console.WriteLine(string.Join(", ", list2));
}
}
}
This approach is much more performant than my first solution, but since your list is only about 12 items long, this is hardly important for your problem.
You're currently only generating one random number and getting one value. What you need to do is put that into a loop that is run half as many times as there are items in the list.
var genRandoms = new Random();
var numberRequired = listOfLines.Count/2;
var output = new List<string>();
for (var i=0; i<numberRequired; i++)
{
var aRandomTeam = genRandoms.Next(listOfLines.Count);
output.Add(listOfLines[aRandomTeam]);
listOfLines.RemoveAt(aRandomTeam);
}
Also, this bit at the beginning:
string[] lines = FormNames.Split(
new[] { Environment.NewLine },
StringSplitOptions.None);
List<string> listOfLines = new List<string>();
foreach (var i in lines)
{
listOfLines.Add(i);
}
string[] result1 = listOfLines.Where(item => item != string.Empty).ToArray();
Can be rewritten as:
var listOfLines = FormNames.Split(
new[] { Environment.NewLine },
StringSplitOptions.RemoveEmptyEntries).ToList();
Removing the empty items as part of the split, and using a built-in method to convert it to a list.
First, try to shuffle the list using the Random function
static class MyExtensions
{
private static Random rng = new Random();
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
then split the list into two using Linq
static void Main(String[] args)
{
List<string> examples = new List<string>();
for(int i=1;i<=12;i++)
{
examples.Add($"Example {i}");
}
examples.Shuffle();
var firstlist = examples.Take(examples.ToArray().Length / 2).ToArray();
Console.WriteLine(String.Join(", ", firstlist));
var secondlist = examples.Skip(examples.ToArray().Length / 2).ToArray();
Console.WriteLine(String.Join(", ", secondlist));
Console.ReadLine();
}
the output looks like this
Example 6, Example 8, Example 3, Example 9, Example 5, Example 2
Example 10, Example 11, Example 4, Example 7, Example 12, Example 1
So I wrote an example in a console app, but the concept works just the same... See comments in code block below
Sample List
var fullList = new List<string>()
{
"ITEM 01", "ITEM 02", "ITEM 03", "ITEM 04", "ITEM 05", "ITEM 06",
"ITEM 07", "ITEM 08", "ITEM 09", "ITEM 10", "ITEM 11", "ITEM 12"
};
Initialize Two Lists to Split Values
var list1 = new List<string>();
var list2 = new List<string>();
Creating Two Random Lists
// Initialize one Random object to use throughout the loop
var random = new Random();
// Note: Start at count and count down because we will alter the count of the list
// so counting up is going to mess up. Ex: Count = 4, Remove 1 (Count = 3), Loop won't go to 4
for(int i = fullList.Count; i > 0; i--)
{
// Pull random index
var randomIndex = random.Next(fullList.Count);
// Pull item at random index
var listItem = fullList[randomIndex];
// If i is even, put it in list 1, else put it in list 2.
// You could do whatever you need to choose a list to put it
if (i % 2 == 0)
list1.Add(listItem);
else
list2.Add(listItem);
// Remove random item from the full list so it doesn't get chosen again
fullList.RemoveAt(randomIndex);
}
Results
Console.WriteLine("LIST 1");
Console.WriteLine(string.Join(Environment.NewLine, list1));
Console.WriteLine();
Console.WriteLine("LIST 2");
Console.WriteLine(string.Join(Environment.NewLine, list2));
-----------------------
LIST 1
ITEM 05
ITEM 04
ITEM 12
ITEM 11
ITEM 08
ITEM 01
LIST 2
ITEM 02
ITEM 03
ITEM 09
ITEM 06
ITEM 10
ITEM 07
Here's a simple solution that falls in line with how you were attempting to solve the problem.
The main logic is as followed:
while there are still items in the master list:
choose a random number [0,list.count) as the current target index
choose a random number [0,1] as the current target list to add to
add the item chosen randomly to the randomly selected list
remove the item chosen from the master list
Here's the code:
var random = new Random();
var list = new List<string> { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
var newList1 = new List<string>();
var newList2 = new List<string>();
while(list.Count > 0)
{
//choose the index randomly
int index = random.Next(list.Count);
//get the item at the randomly chosen index
string curItem = list[index];
//choose the list randomly(1==newList1, 2==newList2)
int listChoice = random.Next(2);
//Add the item to the correct list
if(listChoice == 1)
{
newList1.Add(curItem);
}
else
{
newList2.Add(curItem);
}
//finally, remove the element from the string
list.RemoveAt(index);
}

How can I split a string to store contents in two different arrays in c#?

The string I want to split is an array of strings.
the array contains strings like:
G1,Active
G2,Inactive
G3,Inactive
.
.
G24,Active
Now I want to store the G's in an array, and Active or Inactive in a different array. So far I have tried this which has successfully store all the G's part but I have lost the other part. I used Split fucntion but did not work so I have tried this.
int i = 0;
for(i = 0; i <= grids.Length; i++)
{
string temp = grids[i];
temp = temp.Replace(",", " ");
if (temp.Contains(' '))
{
int index = temp.IndexOf(' ');
grids[i] = temp.Substring(0, index);
}
//System.Console.WriteLine(temp);
}
Please help me how to achieve this goal. I am new to C#.
If I understand the problem correctly - we have an array of strings Eg:
arrayOfStrings[24] =
{
"G1,Active",
"G2,Inactive",
"G3,Active",
...
"G24,Active"
}
Now we want to split each item and store the g part in one array and the status into another.
Working with arrays the solution is to - traverse the arrayOfStrings.
Per each item in the arrayOfStrings we split it by ',' separator.
The Split operation will return another array of two elements the g part and the status - which will be stored respectively into distinct arrays (gArray and statusArray) for later retrieval. Those arrays will have a 1-to-1 relation.
Here is my implementation:
static string[] LoadArray()
{
return new string[]
{
"G1,Active",
"G2,Inactive",
"G3,Active",
"G4,Active",
"G5,Active",
"G6,Inactive",
"G7,Active",
"G8,Active",
"G9,Active",
"G10,Active",
"G11,Inactive",
"G12,Active",
"G13,Active",
"G14,Inactive",
"G15,Active",
"G16,Inactive",
"G17,Active",
"G18,Active",
"G19,Inactive",
"G20,Active",
"G21,Inactive",
"G22,Active",
"G23,Inactive",
"G24,Active"
};
}
static void Main(string[] args)
{
string[] myarrayOfStrings = LoadArray();
string[] gArray = new string[24];
string[] statusArray = new string[24];
int index = 0;
foreach (var item in myarrayOfStrings)
{
var arraySplit = item.Split(',');
gArray[index] = arraySplit[0];
statusArray[index] = arraySplit[1];
index++;
}
for (int i = 0; i < gArray.Length; i++)
{
Console.WriteLine("{0} has status : {1}", gArray[i] , statusArray[i]);
}
Console.ReadLine();
}
seems like you have a list of Gxx,Active my recomendation is first of all you split the string based on the space, which will give you the array previoulsy mentioned doing the next:
string text = "G1,Active G2,Inactive G3,Inactive G24,Active";
string[] splitedGItems = text.Split(" ");
So, now you have an array, and I strongly recommend you to use an object/Tuple/Dictionary depends of what suits you more in the entire scenario. for now i will use Dictionary as it seems to be key-value
Dictionary<string, string> GxListActiveInactive = new Dictionary<string, string>();
foreach(var singleGItems in splitedGItems)
{
string[] definition = singleGItems.Split(",");
GxListActiveInactive.Add(definition[0], definition[1]);
}
What im achiving in this code is create a collection which is key-value, now you have to search the G24 manually doing the next
string G24Value = GxListActiveInactive.FirstOrDefault(a => a.Key == "G24").Value;
just do it :
var splitedArray = YourStringArray.ToDictionary(x=>x.Split(',')[0],x=>x.Split(',')[1]);
var gArray = splitedArray.Keys;
var activeInactiveArray = splitedArray.Values;
I hope it will be useful
You can divide the string using Split; the first part should be the G's, while the second part will be "Active" or "Inactive".
int i;
string[] temp, activity = new string[grids.Length];
for(i = 0; i <= grids.Length; i++)
{
temp = grids[i].Split(',');
grids[i] = temp[0];
activity[i] = temp[1];
}

Can't create nested list because list.Clear doesn't seem to work as I want

I try to load txt file that consists of 200 rows each of different length into nested list so that every sublist inside main list will be equal to row, so there will be 200 sublists.
class MainClass
{
public static void Main (string[] args)
{
List<List<int>> arrayList = new List<List<int>>();
List<int> tmp = new List <int> ();
string[] file = File.ReadAllLines(#"C:\file.txt");
foreach (string line in file) {
string[] linef = line.Split (new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
tmp.Clear ();
for (int n = 0; n < linef.Length; n++) {
tmp.Add (int.Parse (linef [n]));
}
arrayList.Add (tmp);
}
But arrayList seams to contain only last row - whenever i try to get some number, for a example arrayList[78][5], it gives me 5th number from 200th row no matter what the first index is - 78 or other. I think there is issue with tmp.Clear but i cant figure out how to make it work.
Because you are re-adding the same List<int> tmp many times to arrayList, so that at the end
bool areSame = object.ReferenceEquals(arrayList[0], arrayList[1]); // true
You have one List<int> with n references to it (one for each "row" of arrayList)
Change it to:
foreach (string line in file) {
List<int> tmp = new List <int> ();
// No Clear necessary
tmp.Clear() makes your list empty, that is all. The main list contains only 200 references to your tmp list.
You have to call
tmp = new List<int>();
instead of
tmp.Clear();

how to populate complex array of list of array structure c#?

I`m getting hard time of trying to populate that structure:
var arrlist = new List<int[]>()[length];
What I want: an array of fixed length of lists.
Each list would contain unknown number of arrays of length 2.
trying to add following list into above array:
var digfaclist = new List<int[]>();
var factors = new int[2] {i, j};
digfaclist.Add(factors);
I am looping through arrlist and populating it with length 2 arrays in lists. After that I am trying to do smth like:
arrlist[0] = digfaclist;
is it even viable or I should go with some other approach? performance/structure-vice.
something like this?
int count = 15;
List<int[]>[] list = new List<int[]>[count];
for (int i = 0; i < count; i++)
{
list[i] = new List<int[]>(); //you have to initialize them
}
list[0].Add(new []{30, 22});
list[0].Add(new []{11, 22});
foreach (int[] numbers in list[0])
{
Console.WriteLine(string.Join(",",numbers)); //test
}
Is this what you are looking for?
var arr = new int[][] {
new int[] { 1, 2 },
new int[] { 3 ,4 },
new int[] { 5, 6 } }
var arrlist = arr.ToList();
Remember internally a list still maintains an array of items.

Need to add each number 0-x to end of line?

I'm making an app and I'm almost done. I just need to know how I can streamread a txt list and foreach line, add numbers 0-x (x will be the number the user puts in the textbox) and add it to a list. So basically, it would be like this
You import a list with 'dog' on one line, 'cat' on another, and 'fish' on the third. You type '5' into the textbox. the app puts all this into a list:
dog1
dog2
dog3
dog4
dog5
cat1
cat2
cat3
cat4
cat5
fish1
fish2
fish3
fish4
fish5
thanks!
The code below should work for you. I assume you can acquire the count value on your own.
var animals = File.ReadAllLines("yourFile.txt"); //new[] {"dog", "cat", "fish"};
var count = 5;
var merged =
from a in animals
from n in Enumerable.Range(1, count)
select a + n;
foreach (var m in merged)
Console.WriteLine(m); //act on each however you want
You can read a text file with File.ReadAllLines. This gives you an array you can iterate over with foreach.
In this foreach loop you can perform another loop from 1 to the number the user entered. int.Parse comes in handy for converting the string the user entered into a number C# can do something with. For the actual iteration you can use a for loop.
You can then add each item to a list.
There is a good example for reading each line in a filestream here: http://msdn.microsoft.com/en-us/library/e4y2dch9.aspx
private List<string> GetThings(string fileName, int count)
{
string[] lines = File.ReadAllLines(fileName);
List<string> result = new List<string>();
foreach (string item in lines)
{
for (int i = 1; i <= count; i++)
result.Add(item + i.ToString());
}
return result;
}
string[] inputList = File.ReadAllLines("yourFile.txt");
List<String> listOfThings = new List<String>();
foreach (string i in inputList)
{
for (int k = 0; k < 5; k++)
{
listOfThings.Add(i + " " + k.ToString());
}
}
then after that, you can print out the list like this:
foreach (string outp in listOfThings)
{
Console.WriteLine(outp);
}
output:
some value 0
some value 1
some value 2
some value 3
some value 4
some other value 0
some other value 1
some other value 2
some other value 3
some other value 4

Categories