I want to loop through the array which is the result of the array to the Cartesian power n. https://en.wikipedia.org/wiki/Cartesian_product#n-ary_product
This is what I want to achieve, just with n depth:
int[] array = new int[] { 5, -4, ... }
foreach(int a in array) {
foreach(int b in array) {
foreach(int c in array) {
...
int[] NewArray = new int[] { a, b, c, ... }
In Python this is equivalent to:
from itertools import product
for (NewArray in product(array, repeat=n)):
print(NewArray)
I do not know how I can implement this in C#.
Any help would be highly appreciated. Thanks.
You can implement a cartesian product with a little math and yield return:
static public IEnumerable<T[]> Product<T>(IList<T> items, int repeat) {
var total = (int)Math.Pow(items.Count, repeat);
var res = new T[repeat];
for (var i = 0 ; i != total ; i++) {
var n = i;
for (var j = repeat-1 ; j >= 0 ; j--) {
res[j] = items[n % items.Count];
n /= items.Count;
}
yield return res;
}
}
Calling it like this
foreach (var arr in Product(new[] {"quick", "brown", "fox"}, 3)) {
Console.WriteLine(string.Join("-", arr));
}
produces the following output:
quick-quick-quick
quick-quick-brown
quick-quick-fox
quick-brown-quick
quick-brown-brown
quick-brown-fox
quick-fox-quick
quick-fox-brown
quick-fox-fox
brown-quick-quick
brown-quick-brown
brown-quick-fox
brown-brown-quick
brown-brown-brown
brown-brown-fox
brown-fox-quick
brown-fox-brown
brown-fox-fox
fox-quick-quick
fox-quick-brown
fox-quick-fox
fox-brown-quick
fox-brown-brown
fox-brown-fox
fox-fox-quick
fox-fox-brown
fox-fox-fox
Demo.
you can calculate cartesian product of two arrays like below
string[][] CartesianProduct(string[] arr1, string[] arr2)
{
// for each s1 in arr1, extract arr2,
// then pass s1 and s2 into a newly-made string array.
return arr1.SelectMany(s1 => arr2, (s1, s2) => new string[] { s1, s2 })
.ToArray();
}
Lets say you have two array namely
string[] set1 = new string[] { "a", "b", "c" };
string[] set2 = new string[] { "x", "y", "z" };
make a call to CartesianProduct function which would return the resulting value like below.
var cartesionProduct = CartesianProduct (set1,set2);
Related
I have a string myString that can contain a variable number of pairs separated by commas, such as: "a=1,b=2,c=3" or "c=5,b=4" or "t=12".
I also have a set integer variables, named a, b, c, ..., z, all set to 0.
I want to analyze myString and assign the values from string to each variable.
I can only thing of an inefficient way of doing this, using switch and case (i.e. if myString contains 'a', extract value of 'a' and assign it to variable named 'a'). Any ideas of how to write better code for this operation?
void Test(string myString)
{
int a, b, c, d;
a = b = c = d = 0;
string[] varNames = {"a", "b", "c", "d"};
for(int i = 0; i < varNames.Length; i++)
{
if(myString.IndexOf(varNames[i]) >= 0)
{
VariableWhoseNameIs(varNames[i]) = 3;
}
}
}
Why does the variable names matter? You can just store the pairs in a
Dictionary<string, int>
Dictionary<string, int> values= new Dictionary<string, int>()
{
{ a, 1}
{ b, 2}
};
The when you want to retrieve
var value = values[myString].value;
You can do this:
void Test(string myString)
{
int a, b, c, d;
a = b = c = d = 0;
var assign = new Dictionary<string, Action<int>>()
{
{ "a", n => a = n },
{ "b", n => b = n },
{ "c", n => c = n },
{ "d", n => d = n },
};
string[] varNames = { "a", "b", "c", "d" };
for (int i = 0; i < varNames.Length; i++)
{
if (myString.IndexOf(varNames[i]) >= 0)
{
assign[varNames[i]](3);
}
}
}
But it is still very similar to a case statement. The only difference is that you build the assignments at run-time so you have more flexibility in how to create the dictionary - i.e. built across multiple places in your code.
I want to make a string array with values of names and some numbers(which are strings)
i want to pass them into a function that will take the array and then split them into an object jagged array (1 array of strings and 1 array of ints)
the array is:
string[] str= { "toto", "the", "moto", "my", "friend","12","13","14","99","88"};
and the function looks like this:
public object[][] bloop (string[] bstr)
{
}
whats next?
Your scenario looks like bad design that can cause errors and performance issues. The better way is to change code for using generic List<> or something like that. But in your current problem you can use below code:
public object[][] bloop (string[] bstr)
{
var numbers = new List<int>();
var strings = new List<string>();
var result = new object[2][];
foreach(var str in bstr)
{
int number = 0;
if(int.TryParse(str, out number))
{
numbers.Add(number);
}
else
{
strings.Add(str);
}
}
result[0] = strings.ToArray();
result[1] = numbers.ToArray();
return result;
}
public static object[][] bloop(string[] bstr)
{
object[][] result = new object[2][] { new object[bstr.Length], new object[bstr.Length] };
int sFlag = 0, iFlag = 0, val;
foreach (string str in bstr)
if (int.TryParse(str, out val))
result[1][iFlag++] = val;
else
result[0][sFlag++] = str;
return result;
}
I agree that your requirement sounds odd and should be solved with a different approach. However, this will do what you want:
public T[][] Bloop<T>(T[] items)
{
if (items == null) throw new ArgumentNullException("items");
if (items.Length == 1) return new T[][] { items, new T[] { } };
int firstLength = (int) Math.Ceiling((double)items.Length / 2);
T[] firstPart = new T[firstLength];
Array.Copy(items, 0, firstPart, 0, firstLength);
int secondLength = (int)Math.Floor((double)items.Length / 2);
T[] secondPart = new T[secondLength];
Array.Copy(items, firstLength, secondPart, 0, secondLength);
return new T[][] { firstPart, secondPart };
}
Your sample:
string[] str= { "toto", "the", "moto", "my", "friend","12","13","14","99","88"};
string[][] result = Bloop(str);
If you need the second array as int[] you could use following:
int[] ints = Array.ConvertAll(result[1], int.Parse);
Linq solution.
You have two groups: first one has items that can be parsed to int and the second group contains all the others, so GroupBy looks quite naturally:
public Object[][] bloop(string[] bstr) {
if (null == bstr)
throw new ArgumentNullException("bstr");
int v;
return bstr
.GroupBy(x => int.TryParse(x, out v))
.OrderBy(chunk => chunk.Key) // let strings be the first
.Select(chunk => chunk.ToArray())
.ToArray();
}
Test:
string[] str = { "toto", "the", "moto", "my", "friend", "12", "13", "14", "99", "88" };
// toto, the, moto, my, friend
// 12, 13, 14, 99, 88
Console.Write(String.Join(Environment.NewLine,
bloop(str).Select(x => String.Join(", ", x))));
Say we have 5 string arrays as such:
string[] a = {"The","Big", "Ant"};
string[] b = {"Big","Ant","Ran"};
string[] c = {"The","Big","Ant"};
string[] d = {"No","Ants","Here"};
string[] e = {"The", "Big", "Ant", "Ran", "Too", "Far"};
Is there a method to compare these strings to each other without looping through them in C# such that only a and c would yield the boolean true? In other words, all elements must be equal and the array must be the same size? Again, without using a loop if possible.
You can use Linq:
bool areEqual = a.SequenceEqual(b);
Try using Enumerable.SequenceEqual:
var equal = Enumerable.SequenceEqual(a, b);
if you want to get array data that differ from another array you can try .Except
string[] array1 = { "aa", "bb", "cc" };
string[] array2 = { "aa" };
string[] DifferArray = array1.Except(array2).ToArray();
Output:
{"bb","cc"}
If you want to compare them all in one go:
string[] a = { "The", "Big", "Ant" };
string[] b = { "Big", "Ant", "Ran" };
string[] c = { "The", "Big", "Ant" };
string[] d = { "No", "Ants", "Here" };
string[] e = { "The", "Big", "Ant", "Ran", "Too", "Far" };
// Add the strings to an IEnumerable (just used List<T> here)
var strings = new List<string[]> { a, b, c, d, e };
// Find all string arrays which match the sequence in a list of string arrays
// that doesn't contain the original string array (by ref)
var eq = strings.Where(toCheck =>
strings.Where(x => x != toCheck)
.Any(y => y.SequenceEqual(toCheck))
);
Returns both matches (you could probably expand this to exclude items which already matched I suppose)
if (a.Length == d.Length)
{
var result = a.Except(d).ToArray();
if (result.Count() == 0)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("NO");
}
}
else
{
Console.WriteLine("NO");
}
I have two arrays:
string[] array1 = {"a","b","c","d","e"}
string[] array1 = {"x","y","a","b","a"}
I want to print the result like this:
a = 3
b = 2
c = 1
d = 1
e = 1
x = 1
y = 1
z = 1
I can run a loop inside the loop and find this out but is there a better way to achieve the same result?
I want to do this in plain C# without using LINQ.
You can use LINQ to accomplish this:
var counts = array1.Concat(array2)
.GroupBy(v => v)
.Select(g => new { Value=g.Key, Number=g.Count() });
foreach(var item in counts.OrderBy(i => i.Value))
Console.WriteLine("{0} = {1}", item.Value, item.Number);
Given that you want to avoid using LINQ and the extension methods for some reason, you could build your own dictionary:
var counts = new Dictionary<string, int>();
foreach(string item in array1)
{
if (counts.ContainsKey(item))
counts[item]++;
else
counts[item] = 1;
}
foreach(string item in array2)
{
if (counts.ContainsKey(item))
counts[item]++;
else
counts[item] = 1;
}
// Print out counts
foreach(var kvp in counts)
Console.WriteLine("{0} = {1}", kvp.Key, kvp.Value);
Note that this doesn't sort the results - if you need them sorted, you'd have to do that as well.
You can use Concat, GroupBy and OrderByDescending:
var both = array1.Concat(array2);
var groups = both.GroupBy(s => s).OrderByDescending(g => g.Count());
Console.Write(
String.Join(
Environment.NewLine,
groups.Select(g => String.Format("{0} = {1}", g.Key, g.Count()))));
This looks like a job for Linq:
var charCounts = array1.Concat(array2)
.GroupBy(c=>c)
.Select(g=>new Tuple<char, int>(g.Key, g.Count());
.OrderBy(t=>t.Item1);
foreach(var result in charCounts)
Console.WriteLine(String.Format("{0} = {1}", t.Item1, t.Item2));
Read through the two arrays and put them into one dictionary. Keys are the members in the array like "a", "b", etc. Values are integers as count. So, if a key, exists, you increment the count; otherwise put the key into dictionary with a value as 1.
Well, most naive implementation based on type of string would be something like this:
class Program
{
static void Main(string[] args)
{
string[] array1 = {"a", "b", "c", "d", "e"};
string[] array2 = {"x", "y", "a", "b", "a"};
var histogram = new Dictionary<string, int>();
Fill(histogram, array1);
Fill(histogram, array2);
foreach (var p in histogram)
{
Console.WriteLine("{0}={1}",p.Key,p.Value);
}
}
private static void Fill(Dictionary<string, int> histogram, string[] a)
{
foreach (string s in a)
{
if (histogram.ContainsKey(s))
histogram[s] += 1;
else
histogram[s] = 1;
}
}
}
which is build dynamic histogram, print.
another simple approach is like this, but it's of worse readability:
static void Main(string[] args)
{
string[] array1 = {"a", "b", "c", "d", "e"};
string[] array2 = {"x", "y", "a", "b", "a"};
string [] concat = new string[array1.Length+array2.Length];
Array.Copy(array1,concat,array1.Length);
Array.Copy(array2,0,concat,array1.Length,array2.Length);
Array.Sort(concat);
int pos = 0;
while(pos<concat.Length)
{
var cur = concat[pos];
int count = 0;
while ( (pos<concat.Length) && (concat[pos]==cur))
{
pos += 1;
count += 1;
}
Console.WriteLine("{0}={1}",cur,count);
}
}
generally - concat, sort, histogram on sorted data.
I have a List
List<string> collection = {"a","b"}
I want to give a numerical value i.e. Weight e.g. 2
What I want is:
For the given weight, get all possible combinations:
a0b0, a1b0, a2b0
a0b1, a1b1, a2b1
a0b2, a2b2
where 0,1,2 are the values from 0 to the given weight value
I am struggle to generate it. Please guide?
If you truly need all possible combinations, use this:
List<string> collection = new List<string> {"a","b"};
List<int> numbers = new List<int> { 0, 1, 2 };
var result =
from a in collection
from b in collection
from n1 in numbers
from n2 in numbers
select a + n1 + b + n2;
This results in 36 items:
a0a0, a0a1, a0a2, a1a0,
a1a1,
a1a2,
a2a0,
a2a1,
a2a2,
a0b0,
a0b1,
a0b2,
a1b0,
a1b1,
a1b2,
a2b0,
a2b1,
a2b2,
b0a0,
b0a1,
b0a2,
b1a0,
b1a1,
b1a2,
b2a0,
b2a1,
b2a2, b0b0, b0b1, b0b2, b1b0, b1b1, b1b2, b2b0, b2b1, b2b2
If you only need the combinations you stated in your question, use this:
List<int> numbers = new List<int> { 0, 1, 2 };
var result =
from n1 in numbers
from n2 in numbers
select "a" + n1 + "b" + n2;
This results in only 9 items:
a0b0,
a0b1,
a0b2,
a1b0,
a1b1,
a1b2,
a2b0,
a2b1,
a2b2
Using Recursion:
static void ShowCombination(List<string> mlist, int value,int current=0,string stringleft="")
{
if (current == mlist.Count-1) // if this is the last item in the list
{
for (int m = 0; m <= value; m++) //loop through the value add it to the existing string-stringleft
{
Console.WriteLine(stringleft + mlist[current]+m.ToString());
}
}
else // if there are more than 1 item left in the list
{
string currentstring = mlist[current]; //get current string in the list eg. "a"
stringleft = stringleft + currentstring ; //reset existing string -- eg "a"
for (int m = 0; m <= value; m++) //loop through the value add it to the existing 'stringleft' pass it and the new current index for recursion
{
string stopass = stringleft + m.ToString(); // eg. "a0"; "a1"
ShowCombination(mlist, value, current + 1, stopass);
}
}
}
Usage:
ShowCombination(new List<string>() {"a", "b"}, 2);
Output:
a0b0
a0b1
a0b2
a1b0
a1b1
a1b2
a2b0
a2b1
a2b2
This adds not much to #Daniel's answer, just the way you make your weight dynamic:
int weight = 2;
List<string> collection1 = new List<string>{ "a", "b" };
var collection2 = Enumerable.Range(0, weight + 1);
var combinations=from str1 in collection1
from int1 in collection2
from str2 in collection1
from int2 in collection2
select str1 + int1 + str2 + int2;
foreach (var combi in combinations)
Console.WriteLine(combi);
Edit: If you want all permutations, have a look at this project to see how it's implemented. It's working great.
http://www.codeproject.com/Articles/26050/Permutations-Combinations-and-Variations-using-C-G
For example:
List<string> collection1 = new List<string> { "a", "b", "c", "d" };
var collection2 = Enumerable.Range(0, weight + 1);
collection1 = collection1.Concat(collection2.Select(i => i.ToString())).ToList();
var permutations = new Facet.Combinatorics.Permutations<String>(collection1);
foreach (IList<String> p in permutations)
{
String combi = String.Join("", p);
}