Populating C# array with another array - c#

I'm trying to populate my first column with the values of the string array.
I'm using the code below. Which is not working as I'm intended to use it. It throws "Object reference not set to an instance of an object". Could someone explain what I'm doing wrong and suggest a correct approach?
private static int i = 0;
public static string[] names = new string[] { "cmd", "EUI", "ts", "fcnt", "port", "freq", "dr", "ack", "gws", "data" };
public static string[,] jdata;
static void Main(string[] args) {
while (i++ < names.Length) {
jdata[i,0] = names[i];
}
}

Try using Lists.
private static int i = 0;
public static string[] names = new string[] { "cmd", "EUI", "ts", "fcnt", "port", "freq", "dr", "ack", "gws", "data" };
public static List<string>[] jdata = new List<string>[names.Length];
static void Main(string[] args)
{
for (int j = 0; j < names.Length; j++) jdata[j] = new List<string>();
while (i < names.Length)
{
jdata[i].Add(names[i]);
i++;
}
Console.ReadKey();
}

You need to initialize your jdata array first. As the parameters you can use the length of the names array and the number of columns you want.
Also if your i variable is 0 at the beginning, you should increment it after you added a name to the new array or you will get a index out of range exception.
private static int i = 0;
public static string[] names = new string[] { "cmd", "EUI", "ts", "fcnt", "port", "freq", "dr", "ack", "gws", "data" };
public static string[,] jdata;
static void Main(string[] args) {
jdata = new string[names.Length, 1];
while (i < names.Length) {
jdata[i,0] = names[i];
i++;
}
}

to be able to use an object in a method it has to be instantiated first!
Your array jdata has the value null so you cannot access it.
Initialize it first and give it the proper dimensions, so that it is clear how much memory has to be acquired in advance:
public static string[,] jdata = new string[names.Length, 1];
Also if you want to use your while-loop as it is you need to start with i at -1. Otherwise you will skip the first entry. And you should only run until names.Length-1
while (i++ < names.Length-1)
{
jdata[i, 0] = names[i];
}
Why not using a classic for-loop? It does not byte:
for (int i = 0; i < names.Length; i++)
{
jdata[i, 0] = names[i];
}
Am I able to change the size later? Meaning: changing value 1 to another size?
If you want to do that I would suggest to use a List. The Add method allows you to extend the size of the List. In this example it is a List of Lists, which you can imagine as a table with columns and rows. Only the not all columns have necessarily the same amount of rows.
static void Main(string[] args)
{
List<string> names = new List<string> { "cmd", "EUI", "ts", "fcnt", "port", "freq", "dr", "ack", "gws", "data" };
List<List<string>> jdata = new List<System.Collections.Generic.List<string>>
jdata.Add(names);
Console.ReadKey();
}
This has 2 Advantages:
1) The lists that you save in your columns can have different lengths
2) you can remove and add values as you please
To access the first column you can just use the [ ] operator:
List<string> savednames = jdata[0];

jdata is null..
private static int i = 0;
public static string[] names = new string[] { "cmd", "EUI", "ts", "fcnt", "port", "freq", "dr", "ack", "gws", "data" };
public static string[,] jdata = new string[names.Length, 1];
static void Main(string[] args)
{
while (i++ < names.Length)
{
jdata[i, 0] = names[i];
}
}

Related

Putting two 1D arrays into one 2D array in c#

Hey guys i have two 1D arrays one with names and one with phonenumbers:
private string[] names = { "xaw", "Tommy", "Alan", "Sergio", "Adam", "Pablo" };
private string[] phones = { "535-4213", "535-0421", "722-352", "070-3531", "343-2324", "344-2223" };
I want to put them into one 2D array.
also do i have to declare array size like this:
string[,] phonesNames = new string[6,2]
or can i leave it like this:
(without declaration of size? Will it work in this case?)
string[,] phonesNames;
The result should be pairs so phoneNames[0,0] is xaw and phoneNames[0,1] is 535-4213 like this:
Xaw 535-4213
Tommy 535-0421
Alan 722-352
Sergio 070-3531
Adam 343-2324
Pablo 344-2223
I would greatly appreciate if you helped me please.
#edit This is actually not the solution because it only appears as sorted with Console.Writeline() the array is now [2,6] but the thing i was searching for was sorted array [6,2]
private static void Main(string[] args)
{
string[] names = { "xaw", "Tommy", "Alan", "Sergio", "Adam", "Pablo" };
string[] phones = { "535-4213", "535-0421", "722-352", "070-3531", "343-2324", "344-2223" };
string[,] phonesNames = new string[2, names.Length];
for (var i = 0; i < names.Length; i++)
{
phonesNames[0, i] = names[i];
phonesNames[1, i] = phones[i];
}
for (int i = 0; i < names.Length; i++)
Console.WriteLine("{0} {1}", phonesNames[0,i], phonesNames[1,i]);
}
}
The solution is in just 2 lines of code in for loop
for (int dimension = 0; dimension < 6; dimension++)
{
phonesNames[dimension, 0] = names[dimension];
phonesNames[dimension, 1] = phones[dimension];
}
string[] names = { "xaw", "Tommy", "Alan", "Sergio", "Adam", "Pablo" };
string[] phones = { "535-4213", "535-0421", "722-352", "070-3531", "343-2324", "344-2223" };
string[][] phoneNames = new string[2][];
phoneNames[0] = names;
phoneNames[1] = phones;
for (int i = 0; i < names.Length; i++)
Console.WriteLine("{0} {1}", phoneNames[0][i], phoneNames[1][i]);
[![enter image description here][1]][1]
Also, you can use ZIP Method
(https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.zip?view=net-6.0)\
string[] names = { "xaw", "Tommy", "Alan", "Sergio", "Adam", "Pablo" };
string[] phones = { "535-4213", "535-0421", "722-352", "070-3531", "343-2324", "344-2223" };
var zipped = names.Zip(phones, (one, two) => one + " " + two);
foreach(string name in zipped)
{
Console.WriteLine(name);
}
Output
xaw 535-4213
Tommy 535-0421
Alan 722-352
Sergio 070-3531
Adam 343-2324
Pablo 344-2223
If you want to combine the two 1D arrays into one 2D array, this is what I will do:
internal class Program
{
private static readonly string[] names = { "xaw", "Tommy", "Alan", "Sergio", "Adam", "Pablo" };
private static readonly string[] phones = { "535-4213", "535-0421", "722-352", "070-3531", "343-2324", "344-2223" };
private static void Main(string[] args)
{
string[,] phonesNames = new string[2, names.Length];
for (var i = 0; i < names.Length; i++)
{
phonesNames[0, i] = names[i];
phonesNames[1, i] = phones[i];
}
// loop through all columns
for (int i = 0; i < phonesNames.GetLength(1); i++)
{
var phoneName = GetColumn(phonesNames, i);
Console.WriteLine(string.Join(" ", phoneName));
}
}
static string[] GetColumn(string[,] matrix, int columnNumber)
{
return Enumerable.Range(0, matrix.GetLength(0))
.Select(x => matrix[x, columnNumber])
.ToArray();
}
}
Output:
xaw 535-4213
Tommy 535-0421
Alan 722-352
Sergio 070-3531
Adam 343-2324
Pablo 344-2223
Visualize PhoneNames 2D Array:
To access a specific cell, you simply use:
Console.WriteLine(phonesNames[0,2]); // Alan
To access a whole column, e.g. 4th column:
var column4 = GetColumn(phonesNames, 4);
Console.WriteLine(string.Join(" ", column4));
// output = Adam 343-2324

Why a method is modifying a List<string> variable in my Load Page?

I want to create two List with methods, the first method create a new list, and the second modify the first one but return a new one. For example, the first list has 200 items, and after add and delete some items in the second method, the returned one has 120 items.
But the second method is actually modifying the first list (now both list has 120 items).
What am I doing wrong?.
PD. I'm learning
protected void Page_Load(object sender, EventArgs e)
{
List<string> firstList = OEEClass.GetCompleteListDocument(DateTime.Today, "BZX"); // Let say it has 200 items
List<string> modifiedList = OEEClass.ModifyList(firstList); // The returned list has less items
}
public class OEEClass
{
public static List<string> GetCompleteListDocument(DateTime Fecha, string noMaquina)
{
var rawDoc = new HtmlDocument();
var tempList = new List<string>();
string url = #"C:/www/WPCS-Feedback/" + Fecha.Year + "/" + Fecha.Month + "/" + Fecha.Day.ToString("d2") + "/" + "Production state data.htm";
if (File.Exists(url) == true)
{
rawDoc.Load(url);
string cleanString = rawDoc.DocumentNode.InnerText.Trim().Replace(" ", "");
cleanString = Regex.Replace(cleanString, #"^\s+$[\r\n]*", string.Empty, RegexOptions.Multiline);
tempList = Regex.Split(cleanString, "\r\n|\r|\n").ToList();
tempList.RemoveRange(0, 5);
for (int j = 0; j < tempList.Count; j++)
{
if (tempList[j].StartsWith("ProductionTerminated") || tempList[j].StartsWith("ProductionInterrumpted"))
{
tempList.Insert(j + 4, "PressSingleCycleActivated=0");
}
}
}
return tempList;
}
public static List<string> ModifyList(List<string> completeListDocument)
{
for (int i = 0; i < completeListDocument.Count; i++)
{
if (completeListDocument[i].StartsWith("MachineSetup"))
{
completeListDocument.RemoveRange(i, 6);
i--;
}
}
return completeListDocument;
}
}
The simplest thing you can do is make a copy of your list before modifying it:
public static List<string> ModifyList(List<string> completeListDocument)
{
var results = new List<string>(completeListDocument);
for (int i = 0; i < results.Count; i++)
{
if (results[i].StartsWith("MachineSetup"))
{
results.RemoveRange(i, 6);
i--;
}
}
return results;
}

How to check whether a word is composed of other strings in an array

I want to check whether a string is built from another two strings within a given string set.
For example, given the following array:
var arr = new string[] { "b", "at", "bat", "ct", "ll", "ball", "ba"};
I want to return only "bat" and "ball".
That's because they can be composed from two other elements in the array like so:
"bat" = "b" + "at"
"ball" = "ba" + "ll"
I have tried doing it with a foreach loop, but I'm not quite getting it right.
Any help will be much appreciated.
I have done something like
foreach(var x in list)
{
if (dataaccess.IsThreeCharacters(x))
{
for (int i = 0; i < arr.Length; i++)
{
for (int j = i; j < arr.Length; j++)
{
if(x == arr[i] + arr[j])
{
newlist.Add(x);
}
}
}
}
}
This will give you all of the values that can be composed from other values in the sequence:
var values = new HashSet<string>(new[] { "b", "at", "bat", "ct", "ll", "ball", "ba" });
var compositeValues =
from value in values
from otherValue in values
where value != otherValue
let compositeValue = value + otherValue
where values.Contains(compositeValue)
select compositeValue;
Notice the use of HashSet<string>, which gives O(1) lookup performance, as opposed to the O(N) of an array.
This should work although I'm not vouching for efficiency!
static void Main(string[] args)
{
var arr = new string[] { "b", "at", "bat", "ct", "ll", "ball", "ba" };
var composites = from s in arr
from lhs in arr
from rhs in arr
where s == string.Concat(lhs, rhs)
select s;
foreach (var composite in composites)
{
Console.WriteLine(composite);
}
Console.ReadLine();
}

From List<string[]> to String[,]

I have a problem here and it seems that my brain has just left the building so I need you guys to help me out. I have an API - method which requires a multidimensional string array. It looks like this:
string[,] specialMacroArray = new string[,] { { "#macro#", "text1" }, {"#secondmacro#", "text2"} }
The contents of the array are calculated throughout my method and therefor I cannot write it like above. So I put the values in a List throughout my code like this:
List<string[]> specialMacros = new List<string[]>();
specialMacros.Add(new string[] { "#macro#", text1 });
specialMacros.Add(new string[] { "#secondmacro#", "text2" });
So far so good... but now I want to convert the list to the multidimensional array. But I can't figure out how.
specialMacroArray = specialMacros.ToArray()
I am using the .NET 3.5 Framework in C#
Thanx in advance
For this case you could just do this:
specialMacroArray = new string[specialMacros.Count, 2];
for (int i = 0; i < specialMacros.Count; i++)
{
specialMacroArray[i, 0] = specialMacros[i][0];
specialMacroArray[i, 1] = specialMacros[i][1];
}
You'll probably have to do it manually. Something like this:
string[,] array = new string[specialMacroArray.Count, 2]
for (int i=0; i<specialMacroArray.Count; ++i)
{
array[i, 0] = specialMacroArray[i][0];
array[i, 1] = specialMacroArray[i][1];
}
This should help you
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace sandbox
{
class Program
{
static void Main(string[] args)
{
List<string[]> specialMacros = new List<string[]>();
specialMacros.Add(new string[] { "#macro#", "text1" });
specialMacros.Add(new string[] { "#secondmacro#", "text2" });
var op = specialMacros.ToMultiDimensionalArray();
Console.Read();
}
}
public static class ArrayHelper
{
public static string[,] ToMultiDimensionalArray(this List<string[]> dt)
{
int col = dt.FirstOrDefault().ToList().Count();
string[,] arr = new string[dt.Count, col];
int r = 0;
foreach (string[] dr in dt)
{
for (int c = 0; c < col; c++)
{
arr[r, c] = dr[c];
}
r++;
}
return arr;
}
}
}
Based on the some of comments I have edited the function but I believe this user can make his own judgement and improve the code if they need to.
public static string[,] ToMultiDimensionalArray(this List<string[]> dt)
{
if (dt.Count == 0 )
throw new ArgumentException("Input arg has no elemets");
int col = dt[0].Count();
string[,] arr = new string[dt.Count, col];
int r = 0;
foreach (string[] dr in dt)
{
for (int c = 0; c < col; c++)
{
arr[r, c] = dr[c];
}
r++;
}
return arr;
}
string[][] specialMacroArray = new string[][] { new string[] { "#macro#", "text1" }, new string[] { "#secondmacro#", "text2" } };
List<string[]> specialMacros = new List<string[]>();
specialMacros.Add(new string[] { "#macro1#", "text1" });
specialMacros.Add(new string[] { "#secondmacro#", "text2" });
specialMacroArray = specialMacros.ToArray();
works fine, no loop is needed... all u have to do is change string[,] to string[][] (that's array of array, initializes in a bit diff way)
updated code:
List<string[,]> specialMacros = new List<string[,]>();
specialMacros.Add(new string[,] { { "#secondmacro#", "text2" }, { "#secondmacro#", "text2" } });
specialMacroArray =specialMacros[0];

C# Permutation of an array of arraylists?

I have an ArrayList[] myList and I am trying to create a list of all the permutations of the values in the arrays.
EXAMPLE: (all values are strings)
myList[0] = { "1", "5", "3", "9" };
myList[1] = { "2", "3" };
myList[2] = { "93" };
The count of myList can be varied so its length is not known beforehand.
I would like to be able to generate a list of all the permutations similar to the following (but with some additional formatting).
1 2 93
1 3 93
5 2 93
5 3 93
3 2 93
3 3 93
9 2 93
9 3 93
Does this make sense of what I am trying to accomplish? I can't seem to come up with a good method for doing this, (if any).
Edit:
I am not sure if recursion would interfere with my desire to format the output in my own manner. Sorry I did not mention before what my formatting was.
I want to end up building a string[] array of all the combinations that follows the format like below:
for the "1 2 93" permutation
I want the output to be "val0=1;val1=2;val2=93;"
I will experiment with recursion for now. Thank you DrJokepu
I'm surprised nobody posted the LINQ solution.
from val0 in new []{ "1", "5", "3", "9" }
from val1 in new []{ "2", "3" }
from val2 in new []{ "93" }
select String.Format("val0={0};val1={1};val2={2}", val0, val1, val2)
Recursive solution
static List<string> foo(int a, List<Array> x)
{
List<string> retval= new List<string>();
if (a == x.Count)
{
retval.Add("");
return retval;
}
foreach (Object y in x[a])
{
foreach (string x2 in foo(a + 1, x))
{
retval.Add(y.ToString() + " " + x2.ToString());
}
}
return retval;
}
static void Main(string[] args)
{
List<Array> myList = new List<Array>();
myList.Add(new string[0]);
myList.Add(new string[0]);
myList.Add(new string[0]);
myList[0] = new string[]{ "1", "5", "3", "9" };
myList[1] = new string[] { "2", "3" };
myList[2] = new string[] { "93" };
foreach (string x in foo(0, myList))
{
Console.WriteLine(x);
}
Console.ReadKey();
}
Note that it would be pretty easy to return a list or array instead of a string by changing the return to be a list of lists of strings and changing the retval.add call to work with a list instead of using concatenation.
How it works:
This is a classic recursive algorithm. The base case is foo(myList.Count, myList), which returns a List containing one element, the empty string. The permutation of a list of n string arrays s1, s2, ..., sN is equal to every member of sA1 prefixed to the permutation of n-1 string arrays, s2, ..., sN. The base case is just there to provide something for each element of sN to be concatenated to.
I recently ran across a similar problem in a project of mine and stumbled on this question. I needed a non-recursive solution that could work with lists of arbitrary objects. Here's what I came up with. Basically I'm forming a list of enumerators for each of the sub-lists and incrementing them iteratively.
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<IEnumerable<T>> lists)
{
// Check against an empty list.
if (!lists.Any())
{
yield break;
}
// Create a list of iterators into each of the sub-lists.
List<IEnumerator<T>> iterators = new List<IEnumerator<T>>();
foreach (var list in lists)
{
var it = list.GetEnumerator();
// Ensure empty sub-lists are excluded.
if (!it.MoveNext())
{
continue;
}
iterators.Add(it);
}
bool done = false;
while (!done)
{
// Return the current state of all the iterator, this permutation.
yield return from it in iterators select it.Current;
// Move to the next permutation.
bool recurse = false;
var mainIt = iterators.GetEnumerator();
mainIt.MoveNext(); // Move to the first, succeeds; the main list is not empty.
do
{
recurse = false;
var subIt = mainIt.Current;
if (!subIt.MoveNext())
{
subIt.Reset(); // Note the sub-list must be a reset-able IEnumerable!
subIt.MoveNext(); // Move to the first, succeeds; each sub-list is not empty.
if (!mainIt.MoveNext())
{
done = true;
}
else
{
recurse = true;
}
}
}
while (recurse);
}
}
You could use factoradics to generate the enumeration of permutations. Try this article on MSDN for an implementation in C#.
This will work no matter how many arrays you add to your myList:
static void Main(string[] args)
{
string[][] myList = new string[3][];
myList[0] = new string[] { "1", "5", "3", "9" };
myList[1] = new string[] { "2", "3" };
myList[2] = new string[] { "93" };
List<string> permutations = new List<string>(myList[0]);
for (int i = 1; i < myList.Length; ++i)
{
permutations = RecursiveAppend(permutations, myList[i]);
}
//at this point the permutations variable contains all permutations
}
static List<string> RecursiveAppend(List<string> priorPermutations, string[] additions)
{
List<string> newPermutationsResult = new List<string>();
foreach (string priorPermutation in priorPermutations)
{
foreach (string addition in additions)
{
newPermutationsResult.Add(priorPermutation + ":" + addition);
}
}
return newPermutationsResult;
}
Note that it's not really recursive. Probably a misleading function name.
Here is a version that adheres to your new requirements. Note the section where I output to console, this is where you can do your own formatting:
static void Main(string[] args)
{
string[][] myList = new string[3][];
myList[0] = new string[] { "1", "5", "3", "9" };
myList[1] = new string[] { "2", "3" };
myList[2] = new string[] { "93" };
List<List<string>> permutations = new List<List<string>>();
foreach (string init in myList[0])
{
List<string> temp = new List<string>();
temp.Add(init);
permutations.Add(temp);
}
for (int i = 1; i < myList.Length; ++i)
{
permutations = RecursiveAppend(permutations, myList[i]);
}
//at this point the permutations variable contains all permutations
foreach (List<string> list in permutations)
{
foreach (string item in list)
{
Console.Write(item + ":");
}
Console.WriteLine();
}
}
static List<List<string>> RecursiveAppend(List<List<string>> priorPermutations, string[] additions)
{
List<List<string>> newPermutationsResult = new List<List<string>>();
foreach (List<string> priorPermutation in priorPermutations)
{
foreach (string addition in additions)
{
List<string> priorWithAddition = new List<string>(priorPermutation);
priorWithAddition.Add(addition);
newPermutationsResult.Add(priorWithAddition);
}
}
return newPermutationsResult;
}
What you are asking for is called the Cartesian Product. Once you know what its called, there are several similar questions on Stack Overflow. They all seem to end up pointing to an answer which ended up written as a blog post:
http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx
Non-recursive solution:
foreach (String s1 in array1) {
foreach (String s2 in array2) {
foreach (String s3 in array3) {
String result = s1 + " " + s2 + " " + s3;
//do something with the result
}
}
}
Recursive solution:
private ArrayList<String> permute(ArrayList<ArrayList<String>> ar, int startIndex) {
if (ar.Count == 1) {
foreach(String s in ar.Value(0)) {
ar.Value(0) = "val" + startIndex + "=" + ar.Value(0);
return ar.Value(0);
}
ArrayList<String> ret = new ArrayList<String>();
ArrayList<String> tmp1 ar.Value(0);
ar.remove(0);
ArrayList<String> tmp2 = permute(ar, startIndex+1);
foreach (String s in tmp1) {
foreach (String s2 in tmp2) {
ret.Add("val" + startIndex + "=" + s + " " + s2);
}
}
return ret;
}
Here is a generic recursive function that I wrote (and an overload that may be convenient to call):
Public Shared Function GetCombinationsFromIEnumerables(ByRef chain() As Object, ByRef IEnumerables As IEnumerable(Of IEnumerable(Of Object))) As List(Of Object())
Dim Combinations As New List(Of Object())
If IEnumerables.Any Then
For Each v In IEnumerables.First
Combinations.AddRange(GetCombinationsFromIEnumerables(chain.Concat(New Object() {v}).ToArray, IEnumerables.Skip(1)).ToArray)
Next
Else
Combinations.Add(chain)
End If
Return Combinations
End Function
Public Shared Function GetCombinationsFromIEnumerables(ByVal ParamArray IEnumerables() As IEnumerable(Of Object)) As List(Of Object())
Return GetCombinationsFromIEnumerables(chain:=New Object() {}, IEnumerables:=IEnumerables.AsEnumerable)
End Function
And the equivalent in C#:
public static List<object[]> GetCombinationsFromIEnumerables(ref object[] chain, ref IEnumerable<IEnumerable<object>> IEnumerables)
{
List<object[]> Combinations = new List<object[]>();
if (IEnumerables.Any) {
foreach ( v in IEnumerables.First) {
Combinations.AddRange(GetCombinationsFromIEnumerables(chain.Concat(new object[] { v }).ToArray, IEnumerables.Skip(1)).ToArray);
}
} else {
Combinations.Add(chain);
}
return Combinations;
}
public static List<object[]> GetCombinationsFromIEnumerables(params IEnumerable<object>[] IEnumerables)
{
return GetCombinationsFromIEnumerables(chain = new object[], IEnumerables = IEnumerables.AsEnumerable);
}
Easy to use:
Dim list1 = New String() {"hello", "bonjour", "hallo", "hola"}
Dim list2 = New String() {"Erwin", "Larry", "Bill"}
Dim list3 = New String() {"!", ".."}
Dim result = MyLib.GetCombinationsFromIEnumerables(list1, list2, list3)
For Each r In result
Debug.Print(String.Join(" "c, r))
Next
or in C#:
object list1 = new string[] {"hello","bonjour","hallo","hola"};
object list2 = new string[] {"Erwin", "Larry", "Bill"};
object list3 = new string[] {"!",".."};
object result = MyLib.GetCombinationsFromIEnumerables(list1, list2, list3);
foreach (r in result) {
Debug.Print(string.Join(' ', r));
}
Here is a version which uses very little code, and is entirely declarative
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> collection) where T : IComparable
{
if (!collection.Any())
{
return new List<IEnumerable<T>>() {Enumerable.Empty<T>() };
}
var sequence = collection.OrderBy(s => s).ToArray();
return sequence.SelectMany(s => GetPermutations(sequence.Where(s2 => !s2.Equals(s))).Select(sq => (new T[] {s}).Concat(sq)));
}
class Program
{
static void Main(string[] args)
{
var listofInts = new List<List<int>>(3);
listofInts.Add(new List<int>{1, 2, 3});
listofInts.Add(new List<int> { 4,5,6 });
listofInts.Add(new List<int> { 7,8,9,10 });
var temp = CrossJoinLists(listofInts);
foreach (var l in temp)
{
foreach (var i in l)
Console.Write(i + ",");
Console.WriteLine();
}
}
private static IEnumerable<List<T>> CrossJoinLists<T>(IEnumerable<List<T>> listofObjects)
{
var result = from obj in listofObjects.First()
select new List<T> {obj};
for (var i = 1; i < listofObjects.Count(); i++)
{
var iLocal = i;
result = from obj in result
from obj2 in listofObjects.ElementAt(iLocal)
select new List<T>(obj){ obj2 };
}
return result;
}
}
Here's a non-recursive, non-Linq solution. I can't help feeling like I could have less looping and calculate the positions with division and modulo, but can't quite wrap my head around that.
static void Main(string[] args)
{
//build test list
List<string[]> myList = new List<string[]>();
myList.Add(new string[0]);
myList.Add(new string[0]);
myList.Add(new string[0]);
myList[0] = new string[] { "1", "2", "3"};
myList[1] = new string[] { "4", "5" };
myList[2] = new string[] { "7", "8", "9" };
object[][] xProds = GetProducts(myList.ToArray());
foreach(object[] os in xProds)
{
foreach(object o in os)
{
Console.Write(o.ToString() + " ");
}
Console.WriteLine();
}
Console.ReadKey();
}
static object[][] GetProducts(object[][] jaggedArray){
int numLists = jaggedArray.Length;
int nProducts = 1;
foreach (object[] oArray in jaggedArray)
{
nProducts *= oArray.Length;
}
object[][] productAry = new object[nProducts][];//holds the results
int[] listIdxArray = new int[numLists];
listIdxArray.Initialize();
int listPtr = 0;//point to current list
for(int rowcounter = 0; rowcounter < nProducts; rowcounter++)
{
//create a result row
object[] prodRow = new object[numLists];
//get values for each column
for(int i=0;i<numLists;i++)
{
prodRow[i] = jaggedArray[i][listIdxArray[i]];
}
productAry[rowcounter] = prodRow;
//move the list pointer
//possible states
// 1) in a list, has room to move down
// 2) at bottom of list, can move to next list
// 3) at bottom of list, no more lists left
//in a list, can move down
if (listIdxArray[listPtr] < (jaggedArray[listPtr].Length - 1))
{
listIdxArray[listPtr]++;
}
else
{
//can move to next column?
//move the pointer over until we find a list, or run out of room
while (listPtr < numLists && listIdxArray[listPtr] >= (jaggedArray[listPtr].Length - 1))
{
listPtr++;
}
if (listPtr < listIdxArray.Length && listIdxArray[listPtr] < (jaggedArray[listPtr].Length - 1))
{
//zero out the previous stuff
for (int k = 0; k < listPtr; k++)
{
listIdxArray[k] = 0;
}
listIdxArray[listPtr]++;
listPtr = 0;
}
}
}
return productAry;
}
One of the problems I encountred when I was doing this for a very large amount of codes was that with the example brian was given I actually run out of memory. To solve this I used following code.
static void foo(string s, List<Array> x, int a)
{
if (a == x.Count)
{
// output here
Console.WriteLine(s);
}
else
{
foreach (object y in x[a])
{
foo(s + y.ToString(), x, a + 1);
}
}
}
static void Main(string[] args)
{
List<Array> a = new List<Array>();
a.Add(new string[0]);
a.Add(new string[0]);
a.Add(new string[0]);
a[0] = new string[] { "T", "Z" };
a[1] = new string[] { "N", "Z" };
a[2] = new string[] { "3", "2", "Z" };
foo("", a, 0);
Console.Read();
}
private static void GetP(List<List<string>> conditions, List<List<string>> combinations, List<string> conditionCombo, List<string> previousT, int selectCnt)
{
for (int i = 0; i < conditions.Count(); i++)
{
List<string> oneField = conditions[i];
for (int k = 0; k < oneField.Count(); k++)
{
List<string> t = new List<string>(conditionCombo);
t.AddRange(previousT);
t.Add(oneField[k]);
if (selectCnt == t.Count )
{
combinations.Add(t);
continue;
}
GetP(conditions.GetRange(i + 1, conditions.Count - 1 - i), combinations, conditionCombo, t, selectCnt);
}
}
}
List<List<string>> a = new List<List<string>>();
a.Add(new List<string> { "1", "5", "3", "9" });
a.Add(new List<string> { "2", "3" });
a.Add(new List<string> { "93" });
List<List<string>> result = new List<List<string>>();
GetP(a, result, new List<string>(), new List<string>(), a.Count);
Another recursive function.

Categories