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);
}
Related
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);
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.
having a List<int> of integers (for example: 1 - 3 - 4)
how can I convert it in a string of this type?
For example, the output should be:
string values = "1,3,4";
var nums = new List<int> {1, 2, 3};
var result = string.Join(", ", nums);
var ints = new List<int>{1,3,4};
var stringsArray = ints.Select(i=>i.ToString()).ToArray();
var values = string.Join(",", stringsArray);
Another solution would be the use of Aggregate. This is known to be much slower then the other provided solutions!
var ints = new List<int>{1,2,3,4};
var strings =
ints.Select(i => i.ToString(CultureInfo.InvariantCulture))
.Aggregate((s1, s2) => s1 + ", " + s2);
See comments below why you should not use it. Use String.Join or a StringBuilder instead.
public static string ToCommaString(this List<int> list)
{
if (list.Count <= 0)
return ("");
if (list.Count == 1)
return (list[0].ToString());
System.Text.StringBuilder sb = new System.Text.StringBuilder(list[0].ToString());
for (int x = 1; x < list.Count; x++)
sb.Append("," + list[x].ToString());
return (sb.ToString());
}
public static List<int> CommaStringToIntList(this string _s)
{
string[] ss = _s.Split(',');
List<int> list = new List<int>();
foreach (string s in ss)
list.Add(Int32.Parse(s));
return (list);
}
Usage:
String s = "1,2,3,4";
List<int> list = s.CommaStringToIntList();
list.Add(5);
s = list.ToCommaString();
s += ",6";
list = s.CommaStringToIntList();
You can use the delegates for the same
List<int> intList = new List<int>( new int[] {20,22,1,5,1,55,3,10,30});
string intStringList = string.Join(",", intList.ConvertAll<string>(delegate (int i) { return i.ToString(); });
Use the Stringify.Library nuget package
Example 1 (Default delimiter is implicitly taken as comma)
string values = "1,3,4";
var output = new StringConverter().ConvertFrom<List<int>>(values);
Example 2 (Specifying the delimiter explicitly)
string values = "1 ; 3; 4";
var output = new StringConverter().ConvertFrom<List<int>>(values), new ConverterOptions { Delimiter = ';' });
I'm having two List<String> which contains
ListOne
A
B
C
ListTwo
A
B
C
D
Now i need to get the moving combinations to a list string
So the output list will contain
A-B
A-C
A-D
B-C
B-D
C-D
Now i'm using Nested for loop for this.?
Is there any way to do this using LINQ or LAMBDA EXPRESSION
Please help me to do this.
Thanks in advance
Sample Code
List<String> ListOne = new List<string> { "A","B","C"};
List<String> ListTwo = new List<string> { "A", "B", "C", "D" };
List<String> Result = new List<string>(from X in ListOne
from Y in ListTwo
where X!=Y
select string.Format("{0}-{1}", X, Y));
But its not giving the correct output
It produces like
A-B
A-C
A-D
B-A
B-C
B-D
C-A
C-B
C-D
But the required output is like
A-B
A-C
A-D
B-C
B-D
C-D
Sample Code using For Loop
List<String> ResultTwo = new List<string>();
for (int i = 0; i < ListOne.Count; i++)
{
for (int j = 0; j < ListTwo.Count; j++)
{
if(ListOne[i] != ListTwo[j])
if (ResultTwo.Contains(ListOne[i] + "-" + ListTwo[j]) == false && ResultTwo.Contains(ListTwo[j] + "-" + ListOne[i]) == false)
ResultTwo.Add(ListOne[i] + "-" + ListTwo[j]);
}
}
its working fine.... but i just need a simple way ( Using LINQ)
Following your edits this should do the trick:
List<string> ListOne = new List<string>(){"A","B","C"};
List<string> ListTwo = new List<string>(){ "A","B","C","D"};
var result = from a in ListOne
from b in ListTwo
let condition = a.CompareTo(b)
where condition != 0
select condition < 0 ? a + "-" + b : b + "-" + a;
foreach (var v in result.Distinct())
{
Console.WriteLine(v);
}
The second version that preserves order (ItemFromList1 - ItemFromList2):
var result =
from o in
(
from a in ListOne
from b in ListTwo
let condition = a.CompareTo(b)
where condition != 0
select new { a, b, condition }
)
group o by
o.condition < 0 ? o.a + "-" + o.b : o.b + "-" + o.a into g
select g.Select(n => n.a + "-" + n.b).Take(1).ToArray()[0];
So you want all matches except
item matched to itself
item matched to smaller item
and no duplicates.
Here it is:
IEnumerable<string> result =
(
from a in ListOne
from b in ListTwo
where a != b
select a.CompareTo(b) < 0 ? a + "-" + b : b + "-" + a
).Distinct();
Stating the requirement is 90% of the battle.
If you NEED the first item in the pairing to come from the first list, this will do it:
IEnumerable<string> result =
(
from a in ListOne
from b in ListTwo
select new
{
A = a,
B = b,
Combo = a.CompareTo(b) < 0 ? a + "-" + b : b + "-" + a
} into x
group x by x.Combo into g
select g.Select(x2 => x2.A + "-" + x2.B).First()
)
var listA = new List<string> { "A", "B", "C" };
var listB = new List<string> { "A", "B" };
var result = listA.SelectMany((a, indexA) =>
listB.Where((b, indexB) =>
listB.Contains(a) ? !b.Equals(a)&&indexB > indexA
: !b.Equals(a))
.Select(b => string.Format("{0}-{1}", a, b)));
How about the logic of validating is added to the list
class Program
{
static void Main(string[] args)
{
List<string> a = new List<string>() { "C", "D", "L" };
List<string> b = new List<string>() { "C", "L", "C", "D" };
var pairValuesNotEqual = from vara in a
from varb in b
where vara != varb
select new Pair(vara, varb);
Set sets = new Set();
sets.AddRange(pairValuesNotEqual);
foreach (var item in sets)
{
Console.WriteLine(item.First + " - " + item.Second);
}
Console.ReadLine();
}
}
public class Set : List<Pair>
{
public new void AddRange(IEnumerable<Pair> pairs)
{
foreach (var item in pairs)
{
this.Add(item);
}
}
public new void Add(Pair item)
{
if (!IsExists(item))
base.Add(item);
}
private bool IsExists(Pair item)
{
foreach (Pair i in this)
{
if (i.First == item.Second && i.Second == item.First)
return true;
}
return false;
}
}
I dont think LINQ is good enough for this, I got this, but it is not good looking :
var A = from one in ListOne
from two in ListTwo
where one != two
let x = one.CompareTo(two) < 0 ? one : two
let y = one.CompareTo(two) < 0 ? two : one
select new { X = x, Y = y};
var B = A.Distinct().Select(a => a.X + "-" + a.Y);
Acualy, when I clean up your nested foreach code a little bit, I like it more than LINQ:
List<string> outList = new List<string>();
foreach (string s1 in ListOne)
{
foreach (string s2 in ListTwo)
{
if (s1 != s2 &&
!outList.Contains(s1 + "-" + s2) &&
!outList.Contains(s2 + "-" + s1))
{
outList.Add(s1 + "-" + s2);
}
}
}
i have List of int which consists of value 0,0,0,1,2,3,4,0,0 now i like to split this into 3 lists like this list A consists 0,0,0 and List B consists 1,2,3,4 and List C consists 0,0.I know how split using if and for,but how can i do this using linq. usual format i need split in starting some zeros and in middle some values and in last some zeros i need to split this first zeros in one list ,middle values in one list and end zeros in another list as i say in example above here using linq and also i like to take the index that values.
first one.
myList.TakeWhile(x => x==0)
second one.
myList.SkipWhile(x => x==0).TakeWhile(x => x!= 0)
third one.
myList.SkipWhile(x => x==0).SkipWhile(x => x!= 0)
If you want to split by zero sequence then try this code:
static void Main(string[] argv)
{
var list = new[] { 0, 0, 0, 1, 2, 3, 4, 0, 0 };
int groupIndex = 0;
var result = list.Select(
(e, i) =>
{
if (i == 0)
{
return new {val = e, group = groupIndex};
}
else
{
groupIndex =
(e != 0 && list[i - 1] == 0) || (e == 0 && list[i - 1] != 0)
?
groupIndex + 1
: groupIndex;
return new {val = e, group = groupIndex};
}
}
).GroupBy(e => e.group).Select(e => e.Select(o => o.val).ToList()).ToList();
foreach (var item in result)
{
foreach (var val in item)
{
Console.Write(val + ";");
}
Console.WriteLine();
Console.WriteLine("Count:" + item.Count);
Console.WriteLine();
}
Console.ReadLine();
}
Output is:
0;0;0;
Count:3
1;2;3;4;
Count:4
0;0;
Count:2
It is really not clear what is a criteria of split from your question. If I gave wrong answer then explain your question.
You can use the Skip and Take methods exposed by Linq to Objects to grab certain elements of a sequence.
var myList = new int[] {0,0,0,1,2,3,4,0,0};
var list1 = myList.Take(3);
var list2 = myList.Skip(3).Take(4);
var list3 = myList.Skip(7);
You can use Take(n) or Skip(n) in linq
List<int> list = new List<int>();
list.Add(0);
list.Add(0);
list.Add(0);
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(0);
list.Add(0);
var listOne = list.Take(3);
var listSecond = list.Skip(3).Take(4);
var listThird = list.Skip(7);