Splitting and ordering the class c# - c#

I have a class like
Class Foo
{
public string info { get; set; };
public string name { get; set; }
}
Now, info is like :
id=2&pid=6
id=2&pid=6&cid=7
id=2
Now, I want to sort it based on the count of parameters (after spliting by &)
so, it should be
id=2&pid=6&cid=7
id=2&pid=6
id=2
But, I have a list of properties to a class.
The code I wrote is :
private List<Foo> FuncADesc(List<Foo> listObj)
{
Dictionary<string, int> di1 = new Dictionary<string, int>();
for (int i = 0; i < listObj.Count; i++)
{
Dictionary<string,string> diTemp = GetInfo(listObj[i].info);
if (diTemp != null)
{
di1.Add(listObj[i].info, diTemp.Count);
}
}
var list = di1.Keys.ToList();
list.Sort(); // I want to sort by Descending
for (int i = 0; i < list.Count; i++)
{
listObj[i].info = list[i];
listObj[i].name = // ??? //
}
return listObj;
}
//Gets the dictionary after splitting by '&'
private Dictionary<string, string> GetInfo(string Info)
{
Dictionary<string, string> dict1 = null;
if (!string.IsNullOrWhiteSpace(Info))
{
NameValueCollection parse1 = HttpUtility.ParseQueryString(Info);
dict1 = parse1.Cast<string>()
.Select(s => new {Key = s, Value = parse1[s]})
.ToDictionary(dictElement => dictElement.Key.ToLowerInvariant(),
dictElement => dictElement.Value.ToLowerInvariant());
}
return dict1;
}
I want to return listObj but the name and info gets exchange. Is there some easy way or can you point, where can I change ?

You should be able to use LINQ to do something as simple as this:
private List<Foo> FuncADesc(List<Foo> listObj)
{
return listObj.OrderByDescending(x => x.info.Count(c => c == '&')).ToList();
}
OrderByDescending allows you to order the items in a descending fashion. This method uses the number of & characters within the info property of each item as the sort by value.

Related

How to make two list have the same items (but their own sequence)

I have two list object A and B like this:
A=[
{item:1, value:"ex1"},
{item:2, value:"ex1"},
{item:3, value:"ex1"},
{item:4, value:"ex1"}]
B=[{item:1, value:"ex2"},
{item:4, value:"ex2"},
{item:2, value:"ex3"},
{item:5, value:"ex3"}]
How can i do to make B to have same items/values like A and still keep its own sequence for items it already has?
I want B to remove item 5 because A don't have it, and add in item 3 to the end.
I don't want to clone A, I want to modify B to become like A.
What I want is:
Remove items in B when A don't have them: item5
Update items in B when both A and B have them: item1, item2, item4
Add non-existing items to end of B when A have them: item3
So, the result should be like this:
B = [ {item:1, value:"ex1"},
{item:4, value:"ex1"},
{item:2, value:"ex1"},
{item:3, value:"ex1"} ]
Mycode: (This is what i have now)
foreach (myClass itm in A)
{
foreach (myClass fd in B)
{
if (itm.item == fd.item)
{
fd.value = itm.value;
}
}
}
You can write an extension method that merges the lists by iterating over the keys and checking for existence.
static class ExtensionMethods
{
static public void MergeInto<TKey,TValue>(this Dictionary<TKey,TValue> rhs, Dictionary<TKey,TValue> lhs)
{
foreach (var key in rhs.Keys.Union(lhs.Keys).Distinct().ToList())
{
if (!rhs.ContainsKey(key))
{
lhs.Remove(key);
continue;
}
if (!lhs.ContainsKey(key))
{
lhs.Add(key, rhs[key]);
continue;
}
lhs[key] = rhs[key];
}
}
}
Test program:
public class Program
{
public static Dictionary<int,string> A = new Dictionary<int,string>
{
{ 1,"ex1" },
{ 2,"EX2" },
{ 3,"ex3" },
};
public static Dictionary<int,string> B = new Dictionary<int,string>
{
{ 1,"ex1" },
{ 2,"ex2" },
{ 4,"ex4" }
};
public static void Main()
{
A.MergeInto(B);
foreach (var entry in B )
{
Console.WriteLine("{0}={1}", entry.Key, entry.Value);
}
}
}
Output:
1=ex1
2=EX2
3=ex3
Code on DotNetFiddle
Without preserving order
If all you want to do is keep the instance of B, but make it so all its elements match A, you can just do this:
B.Clear();
B.AddRange(A);
Preserving order
If you want to preserve order, you can still use the solution above, but you will need to sort the list that is passed to AddRange(). This is only a little more work.
First, create a lookup table which tells you the order that that Item values originally appeared in. A generic c# Dictionary uses a hash table for the keys, so this is going to end up being more efficient than scanning the List repeatedly. Note that we pass B.Count to the constructor so that it only needs to allocate space once rather than repeatedly as it grows.
var orderBy = new Dictionary<int,int>(B.Count);
for (int i=0; i<B.Count; i++) orderBy.Add(B[i].Item, i);
Now we use our solution, sorting the input list:
B.Clear();
B.AddRange
(
A.OrderBy( item => orderBy.GetValueOrFallback(item.Item, int.MaxValue) )
);
GetValueOrFallback is a simple extension method on Dictionary<,> that makes it simpler to deal with keys that may or may not exist. You pass in the key you want, plus a value to return if the key is not found. In our case we pass int.MaxValue so that new items will be appended to the end.
static public TValue GetValueOrFallback<TKey,TValue>(this Dictionary<TKey,TValue> This, TKey keyToFind, TValue fallbackValue)
{
TValue result;
return This.TryGetValue(keyToFind, out result) ? result : fallbackValue;
}
Example
Put it all together with a test program:
public class MyClass
{
public int Item { get; set; }
public string Value { get; set; }
public override string ToString() { return Item.ToString() + "," + Value; }
}
static public class ExtensionMethods
{
static public TValue ValueOrFallback<TKey,TValue>(this Dictionary<TKey,TValue> This, TKey keyToFind, TValue fallbackValue)
{
TValue result;
return This.TryGetValue(keyToFind, out result) ? result : fallbackValue;
}
static public void MergeInto(this List<MyClass> mergeFrom, List<MyClass> mergeInto)
{
var orderBy = new Dictionary<int,int>(mergeFrom.Count);
for (int i=0; i<mergeInto.Count; i++) orderBy.Add(mergeInto[i].Item, i);
mergeInto.Clear();
mergeInto.AddRange
(
mergeFrom.OrderBy( item => orderBy.ValueOrFallback(item.Item, int.MaxValue) )
);
}
}
public class Program
{
public static List<MyClass> A = new List<MyClass>
{
new MyClass { Item = 2,Value = "EX2" },
new MyClass { Item = 3,Value = "ex3" },
new MyClass { Item = 1,Value = "ex1" }
};
public static List<MyClass> B = new List<MyClass>
{
new MyClass { Item = 1,Value = "ex1" },
new MyClass { Item = 2,Value = "ex2" },
new MyClass { Item = 4,Value = "ex3" },
};
public static void Main()
{
A.MergeInto(B);
foreach (var b in B) Console.WriteLine(b);
}
}
Output:
1,ex1
2,EX2
3,ex3
Code on DotNetFiddle
This is what you specify in the question. I tested it and it works:
class myClass
{
public int item;
public string value;
//ctor:
public myClass(int item, string value) { this.item = item; this.value = value; }
}
static void updateList()
{
var listA = new List<myClass> { new myClass(1, "A1"), new myClass(2, "A2"), new myClass(3, "A3"), new myClass(4, "A4") };
var listB = new List<myClass> { new myClass(1, "B1"), new myClass(4, "B4"), new myClass(2, "B2"), new myClass(5, "B5") };
for (int i = 0; i < listB.Count; i++) //use index to be able to use RemoveAt which is faster
{
var b = listB[i];
var j = listA.FindIndex(x => x.item == b.item);
if (j >= 0) //A has this item, update its value
{
var v = listA[j].value;
if (b.value != v) b.value = v;
}
else //A does not have this item
{
listB.RemoveAt(i);
}
}
foreach (var a in listA)
{
//if (!listB.Contains(a)) listB.Add(a);
if (!listB.Any(b => b.item == a.item)) listB.Add(a);
}
}
You can do something similar to this:
var listA = new List<int> { 1, 3, 5 };
var listB = new List<int> { 1, 4, 3 };
//Removes items in B that aren't in A.
//This will remove 4, leaving the sequence of B as 1,3
listB.RemoveAll(x => !listA.Contains(x));
//Gets items in A that aren't in B
//This will return the number 5
var items = listA.Where(y => !listB.Any(x => x == y));
//Add the items in A that aren't in B to the end of the list
//This adds 5 to the end of the list
foreach(var item in items)
{
listB.Add(item);
}
//List B should be 1,3,5
Console.WriteLine(listB);

Replicating dynamic multi-dimensional array creation of PHP

So, I am converting a project from PHP to C#. Got a Generic List of data as a result of a query
//C# code
public class TermsCommodityModel
{
public int terms_id { get; set; }
public int commodity_id { get; set; }
public int custom { get; set; }
public int calculated { get; set; }
public string name { get; set; }
public string formula { get; set; }
public int division_id { get; set; }
}
I was able to populate it into termsTable which is a List<TermsCommodityModel>. Then the PHP code started looping the termsTable.( C# and PHP codes use same variable for easy conversion). The first line completely altered my datastructure
//PHP code
if (!isset($termsTable[$name]))
$termsTable[$name] = array();
I thought, weird but doable. Then the second condition created another child array and it went on. Now the PHP code looks so,
//PHP Code
if (!isset($termsTable[$name][$t->commodity_id]))
$termsTable[$name][$t->commodity_id] = array();
//.Omitted for brevity
//....
$year = date("Y") + 5;
for ($y = 2008; $y<= $year; $y++) {
$termsTable[$name][$t->commodity_id][$y] = array();
for ($i=1; $i<=12; $i++)
$termsTable[$name][$t->commodity_id][$y][$i] = 0;
}
This is the final data-structure
//PHP Code
$termsTable[$name]
$termsTable[$name][$t->commodity_id]
$termsTable[$name][$t->commodity_id][$y]
$termsTable[$name][$t->commodity_id][$y][$i]
This essentially created an array of an array of an array of an array of an object dynamically. The thing is PHP is a dynamically typed language. It doesn't need to specify a type
Which data-structure in C# could possibly do this? Cant use a tuple as they are hierarchical, right?
Which way to approach this? Any pointers will be extremely helpful as this is kinda important.
I'm not sure how TermsCommodityModel is related to php code, because it's not shown anywhere there as far as I can tell. Anyway, you can achieve syntax similar to php by (ab)using dynamic and DynamicObject. First create class like this:
public class DynamicDictionary : DynamicObject {
private readonly Dictionary<object, object> _dictionary;
public DynamicDictionary() {
_dictionary = new Dictionary<object, object>();
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
// this will be called when you do myDict[index] (but not myDict[index] = something)
if (indexes.Length != 1)
throw new Exception("Only 1-dimensional indexer is supported");
var index = indexes[0];
// if our internal dictionary does not contain this key
// - add new DynamicDictionary for that key and return that
if (_dictionary.ContainsKey(index)) {
_dictionary.Add(index, new DynamicDictionary());
}
result = _dictionary[index];
return true;
}
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) {
// this will be called when you do myDict[index] = value
if (indexes.Length != 1)
throw new Exception("Only 1-dimensional indexer is supported");
var index = indexes[0];
// just set value
_dictionary[index] = value;
return true;
}
}
And use it like this:
dynamic termsTable = new DynamicDictionary();
var name = "name";
int commodityId = 123;
var year = DateTime.Now.Year + 5;
for (int y = 2008; y <= year; y++) {
for (int i = 1; i < 12; i++) {
// that's fine
termsTable[name][commodityId][y][i] = 0;
}
}
// let's see what we've got:
for (int y = 2008; y <= year; y++) {
for (int i = 1; i < 12; i++) {
// that's fine
Console.WriteLine(termsTable[name][commodityId][y][i]);
}
}
To mirror your php code even more, change TryGetIndex like this:
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
// this will be called when you do myDict[index] (but not myDict[index] = something)
if (indexes.Length != 1)
throw new Exception("Only 1-dimensional indexer is supported");
var index = indexes[0];
// if our internal dictionary does not contain this key
// return null
if (!_dictionary.ContainsKey(index)) {
result = null;
}
else {
result = _dictionary[index];
}
return true;
}
Then you need to check if such key already exists (which is a bit better to my mind):
dynamic termsTable = new DynamicDictionary();
var name = "name";
int commodityId = 123;
var year = DateTime.Now.Year + 5;
// need to check if such key exists
// like isset in php
if (termsTable[name] == null)
termsTable[name] = new DynamicDictionary();
if (termsTable[name][commodityId] == null)
termsTable[name][commodityId] = new DynamicDictionary();
for (int y = 2008; y <= year; y++) {
if (termsTable[name][commodityId][y] == null)
termsTable[name][commodityId][y] = new DynamicDictionary();
for (int i = 1; i < 12; i++) {
// that's fine
termsTable[name][commodityId][y][i] = 0;
}
}
Of course type safery is thrown out of the window by doing that, but if you are fine with that - why not.
Although the code in my first answer reproduces the original logic written in PHP, it lacks some very important qualities. It is not self-explanatory, and it is hard to read.
Specifically, things like Dictionary<string, Dictionary<int, Dictionary<int, Dictionary<int, int>>>> is a huge anti-pattern. No one knows what is expected to be in the keys and in the values of this monster data structure. It is too error-prone.
A much better way to factor the code would be as follows:
public class TermsTable
{
private readonly Dictionary<string, IndexByCommodityId> _index;
public TermsTable(IEnumerable<TermsCommodityModel> list)
{
_index = list
.GroupBy(tcm => tcm.name)
.ToDictionary(
tcmGroup => tcmGroup.Key,
tcmGroup => new IndexByCommodityId(tcmGroup));
}
public IndexByCommodityId this[string name] => _index[name];
}
public class IndexByCommodityId
{
private readonly Dictionary<int, IndexByYear> _index;
public IndexByCommodityId(IEnumerable<TermsCommodityModel> list)
{
_index = list.ToDictionary(
keySelector: tcm => tcm.commodity_id,
elementSelector: tcm => new IndexByYear());
}
public IndexByYear this[int commodityId] => _index[commodityId];
}
public class IndexByYear
{
private static readonly int _nowYear = DateTime.Now.Year;
private readonly Dictionary<int, IndexByMonth> _index;
public IndexByYear()
{
_index = Enumerable
.Range(2008, _nowYear - 2008 + 1)
.ToDictionary(
keySelector: year => year,
elementSelector: year => new IndexByMonth());
}
public IndexByMonth this[int year] => _index[year];
}
public class IndexByMonth
{
private readonly Dictionary<int, int> _index;
public IndexByMonth()
{
_index = Enumerable.Range(1, 12).ToDictionary(month => month, month => 0);
}
public int this[int month]
{
get => _index[month];
set => _index[month] = value;
}
}
The code that uses the new data structure would look like this:
// a flat list of TermsCommodityModel, filled with data elsewhere
List<TermsCommodityModel> list = new List<TermsCommodityModel>();
// create our hierarchical index from the above list
TermsTable aBetterTermsTable = new TermsTable(list);
string name = "ABC";
int commodityId = 12345;
int year = 2010;
int month = 10;
int value = aBetterTermsTable[name][commodityId][year][month];
Yes, it is much more code to write, but its worth it. It is easier to read, and less error prone. For instance, one of the benefits is IntelliSense:
I have little knowledge in PHP, but it looks like I can follow. The code you demonstrate in your question is based on associative arrays. In .NET, associative arrays are usually implemented through Dictionary<TKey, TValue> data structure.
You start with a flat List<TermsCommodityModel>, and then you can build hierarchical dictionary-based structures as follows:
// a flat list of TermsCommodityModel, filled with data elsewhere
List<TermsCommodityModel> list = new List<TermsCommodityModel>();
Dictionary<string, Dictionary<int, Dictionary<int, Dictionary<int, int>>>> termsTable = list
.GroupBy(tcm => tcm.name)
.ToDictionary(
tcmGroup => tcmGroup.Key,
tcmGroup => tcmGroup.ToDictionary(
tcm => tcm.commodity_id,
tcm => CreateYearMonthTable()));
and one more helper function:
static Dictionary<int, Dictionary<int, int>> CreateYearMonthTable()
{
var year = DateTime.Now.Year + 5;
return Enumerable
.Range(2008, year - 2008 + 1)
.ToDictionary(
y => y,
y => Enumerable.Range(1, 12).ToDictionary(i => i, i => 0));
}
the following is an example of how you access the leaf values in this data structure:
string name = "ABC";
int commodityId = 12345;
int year = 2010;
int month = 10;
int value = termsTable[name][commodityId][year][month];
EDIT
A better approach to solve the problem is in my second answer:
https://stackoverflow.com/a/47593724/4544845

Property or indexer cannot be assigned to “--” it is read only C# List<Tuple<string, bool>>

I created the following class:
namespace Prototype.ViewModel.MyVM
{
public clas TheVm
{
List<Tuple<string, bool>> list = new List<Tuple<string, bool>>();
public List<Tuple<string, bool>> List
{
get { return this.list; }
set { this.list = value; }
}
}
}
In another code file, I'm trying modify one of the values of the encapsulated List> object:
for (int i = 0; i < anotherList.Count; i++)
{
TheVM.List[i].Item2 = (anotherList[i].Item2 == 1);
}
But I get the following error message:
Property or indexer 'Tuple.Item2' cannot be assigned to “--” it is read only.
How can I solve that?
You will need to create a new Tuple as they are immutable:
for (int i = 0; i < anotherList.Count; i++)
{
TheVM.List[i] = new Tuple<string, bool>(TheVM.List[i].Item1, anotherList[i].Item2 == 1);
}
This being said, I would recommend against using Tuples for view models.
If you need to change one part of the tuple after it is created, you don't need Tuple, just create you own class:
public class MyTuple
{
public MyTuple(string item1, bool item2)
{
Item1 = item1;
Item2 = item2;
}
public string Item1 {get;set;}
public bool Item2 {get;set;}
}
After that you could define your List as :
public List<MyTuple>> List
and will be able to change Item1/Item2

How to compare two lists that contain objects that contain Dictionaries?

I have two Lists (List “A” and List “B”) that hold objects of type “KeyStore”, which is shown below:
public class KeyStore
{
public Dictionary<string, string> PrimaryKeys { get; set; }
public KeyStore(string pkName, string pkValue)
{
PrimaryKeys = new Dictionary<string, string> {{pkName, pkValue}};
}
public KeyStore()
{
PrimaryKeys = new Dictionary<string, string>();
}
}
I need to look at each record in List “A” and see if there is a matching record in List “B”. If there is, then this record needs to be stored in a new list that contains just matching records. A match is considered true if a record’s PrimaryKeys dictionary contains the same number of entries and the same key value combination as a record in List “B”. The order of the entries in the dictionary is not important in testing for equality. If there is a record in List “A” that does not have a match in List “B”, then this needs to be stored in a new list that will only contain records found in List “A”.
Previously I did something similar when I had Lists of strings where I used “Intersect” and “Except” to create lists of matched and non-matched records. I’m assuming that now that I need to compare these KeyStore objects I need to go up a level of complexity. Can anyone offer a solution or advise on how I should approach this problem?
EDIT 1 ----------------
Based on comments, I have created a class that implements IEqualityComparer, as shown below:
class KeyStoreComparer : IEqualityComparer<KeyStore>
{
public bool Equals(KeyStore x, KeyStore y)
{
if (x != null && x.PrimaryKeys.Count == y.PrimaryKeys.Count)
{
return x.PrimaryKeys.Keys.All(k => y.PrimaryKeys.ContainsKey(k)) &&
x.PrimaryKeys.Keys.All(k => x.PrimaryKeys[k].Equals(y.PrimaryKeys[k]));
}
return false;
}
public int GetHashCode(KeyStore obj)
{
return ReferenceEquals(obj, null) ? 0 : obj.GetHashCode();
}
}
I have created some dummy data but when the "Intersect" command is run the above code is never called. Any ideas where I am going wrong?
var ListA = new List<KeyStore>();
ListA.Add(new KeyStore("a", "b"));
ListA.Add(new KeyStore("c", "d"));
var ListB = new List<KeyStore>();
ListB.Add(new KeyStore("a", "b"));
ListB.Add(new KeyStore("x", "y"));
var g = ListA.Intersect(ListB, new KeyStoreComparer());
The code in the "Equals" and "GetHashCode" may not be correct but I'm just trying to get it to get as far as running it before I can improve it.
EDIT 2 ---------------------------------------
I have made various changes to the KeyStore class as shown in the example by “fox” on this page. I still don’t get the overridden functions to be called. As an experiment I tried this:
var result = ListA.Equals(ListB);
When I do this the overridden functions in the KeyStor class don’t run. But if I do this:
var result = ListA[0].Equals(ListB[0]);
The overridden functions do run and give the expected result. Anyone know how I can get this to work for all items in the lists rather than just for individual records?
EDIT 3 ---------------------------------------
The problem I am seeing is that the override works fine for single items, eg:
var a = new KeyStore("a", "b");
var b = new KeyStore("a", "b");
var c = a.Equals(b);
When I run the above my break point on the KeyStore "Equals" function is hit. As soon as I try to do something similar but with a List of KeyStore, the breakpoint is no longer hit. Do I need to do something extra when working with Lists?
public class KeyStore
{
public Dictionary<string, string> PrimaryKeys { get; set; }
public KeyStore(string pkName, string pkValue)
{
PrimaryKeys = new Dictionary<string, string> { { pkName, pkValue } };
}
public KeyStore()
{
PrimaryKeys = new Dictionary<string, string>();
}
public override bool Equals(object obj)
{
// If parameter is null return false.
if (obj == null)
return false;
// If parameter cannot be cast to KeyStore return false.
KeyStore targetKeyStore = obj as KeyStore;
if (targetKeyStore == null)
return false;
return PrimaryKeys.OrderBy(pk => pk.Key).SequenceEqual(targetKeyStore.PrimaryKeys.OrderBy(pk => pk.Key));
}
public override int GetHashCode()
{
StringBuilder content = new StringBuilder();
foreach (var item in PrimaryKeys.OrderBy(pk => pk.Key))
content.AppendFormat("{0}-{1}", item.Key, item.Value);
return content.ToString().GetHashCode();
}
}
Eric Lippert's guide on implementing GetHashCode wrote that "equal items have equal hashes". GetHashCode() implementation above just to show concept, might not suitable for production code.
Overriding the ToString method will help simplify your code quite a bit. See if this helps:
public class KeyStore
{
public SortedDictionary<string, string> PrimaryKeys
{
get;
set;
}
public KeyStore(string pkName, string pkValue)
{
PrimaryKeys = new SortedDictionary<string, string> { { pkName, pkValue } };
}
public KeyStore()
{
PrimaryKeys = new SortedDictionary<string, string>();
}
public override bool Equals(object obj)
{
if(obj == null || (KeyStore)obj == null)
return false;
KeyStore temp = (KeyStore)obj;
return ToString() == temp.ToString();
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public override string ToString()
{
return PrimaryKeys.Count.ToString() + " : \n" + string.Join("\n",(from kvp in PrimaryKeys
let s = kvp.Key + " - " + kvp.Value
select s));
}
}
List<KeyStore> Lista = new List<KeyStore>
{
new KeyStore("testa","testa1"),
new KeyStore("testb","testb1"),
new KeyStore("testc", "testc1")
};
List<KeyStore> Listb = new List<KeyStore>
{
new KeyStore("testa","testa1"),
new KeyStore("testd","testb1"),
new KeyStore("testc", "testa1"),
new KeyStore("teste", "teste1")
};
var Listc = Lista.Intersect(Listb).ToList();
var Listd = Lista.Except(Listb).ToList();
?Listc
Count = 1
[0]: {1 :
testa - testa1}
?Listd
Count = 2
[0]: {1 :
testb - testb1}
[1]: {1 :
testc - testc1}

How to select distinct List<T>'s from a List<List<T>>?

HI, I am working on a simple class to combine items of any type... this is for a poker game, this is how it looks:
public static List<List<T>> combinar<T>(List<T> items, int take)
{
List<List<T>> combs = new List<List<T>>();
var stuff = permutar<T>(items, take);
var all = from s in stuff
select new Tuple<List<T>, string>(s, String.Join("", s.OrderBy(c => c).Select(c => c.ToString())));
var strs = all.Select(s => s.Item2).Distinct();
foreach (var str in strs)
{
combs.Add(all.First(a => a.Item2 == str).Item1);
}
return combs;
}
public static List<List<T>> permutar<T>(List<T> list, int take)
{
List<List<T>> combs = new List<List<T>>();
foreach (var item in list)
{
var newlist = list.Where(i => !i.Equals(item)).ToList();
var returnlist = take <= 1 ? new List<List<T>> { new List<T>() } : permutar(newlist, take - 1);
foreach (var l in returnlist)
{
l.Add(item);
}
combs.AddRange(returnlist);
}
return combs;
}
so permutation works perfect.. but I am having some trouble with combination, when T is Card it takes hell lots of time to complete... so my question is how to select distinct lists form the result of permutation???
this is the Card Class:
public class Card : IComparable
{
Suite _Suite;
public Suite Suite
{
get { return _Suite; }
set { _Suite = value; }
}
Grade _Grade;
public Grade Grade
{
get { return _Grade; }
set { _Grade = value; }
}
string _symbol;
public string Symbol
{
//stuff
}
public PictureBox Picture
{
//stuff
}
public override string ToString()
{
return _Grade.ToString() + " " + _Suite.ToString();
}
public int CompareTo(object obj)
{
Card card = (Card)obj;
return card.Grade > this.Grade ? -1 : card.Grade < this.Grade ? 1 : 0;
}
}
Assuming you don't want to make any big algorithmic changes, your biggest problem here is
combs.Add(all.First().Item1);
That doesn't make any sense. Perhaps you meant
combs.Add(all.First(c => c.Item2 == str)).Item1);
However, that would be very slow; if that's what you want, you should put the results of all into a hash table keyed by the string, and use that instead of looping through Distinct results.
If you wanted to get combinations without computing permutations first, the way to do it would be like this. Given some objects, to find the combinations of length K: if K is 0, return the empty list. Else, for each object, take that object, and then recursively append all the K-minus-1-length combinations of the rest of the objects.

Categories