How To Create a Dictionary Tree in C# - c#

I have the following code:
class Foo<KType, VType>
{
public KType Key;
public VType Value;
public List<Foo<KType, VType>> Children;
}
class Test
{
public Test()
{
var x = new List<Foo<int, string>>()
{
new Foo<int, string>() {Key = 1, Value = "a", Children = new List<Foo<int, string>>()
{
new Foo<int, string>() {Key = 1, Value = "a"},
new Foo<int, string>() {Key = 2, Value = "b"}
}
},
new Foo<int, string>() {Key = 2, Value = "b"}
};
}
}
It works beautifully in allowing me to have a tree of nested "pairs" of {KType, VType}. However, because I have a List and not a Dictionary, I don't have a way of enforcing that the keys will be unique. How can I construct a tree or chain of dictionaries or the equivalent? I'd like to change the underlying type of "Children" to a dictionary, but that takes a KeyValuePair, which takes only 2 items, a key and a value, and there'd be no room for the grandchildren.

As mentioned by #jdweng, the dictionary could map keys to foos:
class Foo<KType, VType>
{
public VType Value;
public Dictionary<KType, Foo<KType, VType>> Children;
}
class Test
{
public Test()
{
var root = new Foo<int, string>
{
Value = "root",
Children = new Dictionary<int, Foo<int, string>>
{
{
1,
new Foo<int, string>
{
Value = "a",
Children = new Dictionary<int, Foo<int, string>>
{
{1, new Foo<int, string> {Value = "a", Children = null}},
{2, new Foo<int, string> {Value = "b", Children = null}}
}
}
},
{
2,
new Foo<int, string>
{
Value = "b",
Children = null
}
}
}
};
}
}

Related

C#: How to get the value of derived class from an IReadOnlyList containing abstract classes

Hi how can I return the first ValueNode's value + the value of the first value in the first ListNode?
Node is the parent abstract class.
ListNode is a derived class containing a list of ValueNodes.
ValueNode is the derived class containing the value.
public static readonly IReadOnlyList<Node> TestData = new List<Node>
{
new ValueNode {Value = "a"},
new ListNode
{
Values = new List<Node>
{
new ValueNode {Value = "b"},
new ValueNode {Value = "c"},
new ListNode
{
Values = new List<Node>
{
new ValueNode {Value = "d"},
new ValueNode {Value = "e"}
}
},
new ListNode
{
Values = new List<Node>
{
new ValueNode {Value = "f"}
}
},
new ValueNode {Value = "g"}
}
},
new ValueNode {Value = "h"},
new ValueNode {Value = "i"},
new ListNode
{
Values = new List<Node>
{
new ValueNode {Value = "j"},
new ValueNode {Value = "k"}
}
},
};
public abstract class Node
{
protected object Data;
}
public class ValueNode : Node
{
public string Value
{
get => (string)Data;
set => Data = value;
}
}
public class ListNode : Node
{
public List<Node> Values
{
get => (List<Node>)Data;
set => Data = value;
}
}
}
}
I would like to know how I could return the value 'a' and the value of 'b' from TestData.
you could use a linq expression to filter for elements with a given type:
IReadOnlyList<Node> testData = new List<Node> { new ValueNode(), new ListNode() };
var valuesOnly = testData.OfType<ValueNode>().ToArray();
which is equivalent to:
var valuesOnly = testData.Where(x => x is ValueNode).ToArray();

Sort List by Value of SubList with where clause LINQ

I have a object structure like so
public class Obj1
{
public string Name {get; set;}
public List<KeyValuePair<int, double>> PairList {get; set;}
}
If I have a list of Obj1, how would I be able to Order that list based on the largest value in Pair list, where key is a particular value. For instance this object.
List<Obj1> foo = new List<Obj1>()
{
new Obj1()
{
Name = "Foo",
PairList = new List<KeyValuePair<int, double>>()
{
new KeyValuePair<int, double>(1,20),
new KeyValuePair<int, double>(2,25),
new KeyValuePair<int, double>(3,30)
}
},
new Obj1()
{
Name = "Bar",
PairList = new List<KeyValuePair<int, double>>()
{
new KeyValuePair<int, double>(1,20),
new KeyValuePair<int, double>(2,60),
new KeyValuePair<int, double>(3,30)
}
},
new Obj1()
{
Name = "Test",
PairList = new List<KeyValuePair<int, double>>()
{
new KeyValuePair<int, double>(1,20),
new KeyValuePair<int, double>(2,35),
new KeyValuePair<int, double>(3,30)
}
}
};
If I want to order by the above list where the Key is 2, I would expect the order of the list to be the following names
Bar
Test
Foo
How can I do this in LINQ?
Try this
var result= foo.OrderByDescending(x => x.PairList[1].Value);
You have to take the max value from PairList and uset it to sort the objects by it.
var result = foo.OrderByDescending(x => x.PairList.Max(v => v.Value));

how to change the value of dictionary using linq based on key?

I have a Dictionary which is of type,
Dictionary<string, string> newdictionary = new Dictionary<string, string>();
newdictionary.Add("12345", "chip1");
newdictionary.Add("23456", "chip2");
Now i have a List which is of type
internal class CustomSerial
{
public string SerialNo { get; set; }
public decimal ecoID { get; set; }
}
var customList = new List<CustomSerial>();
CustomSerial custObj1= new CustomSerial();
custObj1.ecoID =1;
custObj1.SerialNo = "12345";
customList.Add(custObj1);
CustomSerial custObj2 = new CustomSerial();
custObj2.ecoID = 2;
custObj2.SerialNo = "23456";
customList.Add(custObj2);
Now i need to update the Initial dictionary by Filtering the Keys with ther SerialNumber and Replacing the values with the ecoID.
When i try this, it gives
foreach (KeyValuePair<string, string> each in newdictionary)
{
each.Value = customList.Where(t => t.SerialNo == each.Key).Select(t => t.ecoID).ToString();
}
System.Collections.Generic.KeyValuePair.Value' cannot be assigned to -- it is read only
LIN(Q) is a tool to query something not to update it.
However, you can first query what you need to update. For example:
var toUpdate = customList
.Where(c => newdictionary.ContainsKey(c.SerialNo))
.Select(c => new KeyValuePair<string, string>(c.SerialNo, c.ecoID.ToString()));
foreach(var kv in toUpdate)
newdictionary[kv.Key] = kv.Value;
By the way, you get the "KeyValuePair.Value' cannot be assigned to it is read only" exception because aKeyValuePair<TKey, TValue> is a struct which cannot be modified.
You'd have the simplest in this form: though I don't see why you are assigning the same value but the method applies regardless
var dictionary = new Dictionary<string, string>() { { "12345", "chip1" }, { "23456", "chip2" } };
var customList = new List<CustomSerial>() { new CustomSerial() { ecoID = 1, SerialNo = "12345" }, new CustomSerial() { ecoID = 2, SerialNo = "23456" } };
dictionary.Keys.ToList().ForEach(key =>
{
dictionary[key] = customList.FirstOrDefault(c => c.SerialNo == key).SerialNo;
});

Initialize Dictionary<string, List<string>>

I would like to know how do I declare/initialize a dictionary ?
The below one gives error.
Dictionary<string, List<string>> myD = new Dictionary<string, List<string>>()
{
{"tab1", MyList }
};
List <string> MyList = new List<string>() { "1" };
The error is: A field initializer cannot reference the non-static field, method, or property MyList. It is not List declaration coming in front or later after dictionary.
class MyClass
{
Dictionary<string, List<string>> myD = new Dictionary<string, List<string>>()
{
{"tab1", new List<string> { "1" } },
{"tab2", new List<string> { "1","2","3" } },
{"tab3", new List<string> { "one","two" } }
};
}
As Scott Chamberlain said in his answer:
If these are non static field definitions you can not use the field
initializers like that, you must put the data in the constructor.
class MyClass
{
Dictionary<string, List<string>> myD;
List <string> MyList;
public MyClass()
{
MyList = new List<string>() { "1" };
myD = new Dictionary<string, List<string>>()
{
{"tab1", MyList }
};
}
}
Additionally for Static field
private static List<string> MyList = new List<string>()
{
"1"
};
private static Dictionary<string, List<string>> myD = new Dictionary<string, List<string>>()
{
{"tab1", MyList }
};
If these are non static field definitions you can not use the field initializers like that, you must put the data in the constructor.
class MyClass
{
Dictionary<string, List<string>> myD;
List <string> MyList;
public MyClass()
{
MyList = new List<string>() { "1" };
myD = new Dictionary<string, List<string>>()
{
{"tab1", MyList }
};
}
}

How to Sort a List of Objects by dictionary value?

How would I sort this by a chosen dictionary value in Person?
Example: Order List of "Person" by "cars" value descending.
Is that possible with one of those fancy lambda/linq equations?
public class People
{
List<Person> Persons { get; set; }
}
public class Person
{
public Dictionary<string, string> cars { get; set; }
public Dictionary<string, string> houses { get; set; }
public Dictionary<string, string> banks { get; set; }
}
................
People people = new People();
people.Persons = new List<Person>
{
new Person
{
cars = new Dictionary<string, string> { { "volvo", "340050" }, { "bmw", "50545000" } },
houses = new Dictionary<string, string> { { "mansion", "100040000" },{ "cardboard box", "112" } },
banks = new Dictionary<string, string> { { "swiss", "12500330000" }, { "camen", "12000000" } }
},
new Person
{
cars = new Dictionary<string, string> { { "volvo", "34023200" }, { "bmw", "5003300" } },
houses = new Dictionary<string, string> { { "mansion", "1000330000" },{ "cardboard box", "277" } },
banks = new Dictionary<string, string> { { "swiss", "12500044000" }, { "camen", "12000000" } }
},
new Person
{
cars = new Dictionary<string, string> { { "volvo", "3554000" }, { "bmw", "50023200" } },
houses = new Dictionary<string, string> { { "mansion", "1006600000" },{ "cardboard box", "244" } },
banks = new Dictionary<string, string> { { "swiss", "125000544000" }, { "camen", "12000777000" } }
}
};
EDIT / EXAMPLE RESULT:
The result would be a new or reordered list based on a value contained in the dictionary of each Person
Person -> cars -> { "volvo", "34023200" }
Person -> cars -> { "volvo", "3554000" }
Person -> cars -> { "volvo", "340050" }
The new or reordered List would look exactly like this:
people.Persons = new List<Person>
{
new Person
{
cars = new Dictionary<string, string> { { "volvo", "34023200" }, { "bmw", "5003300" } },
houses = new Dictionary<string, string> { { "mansion", "1000330000" },{ "cardboard box", "277" } },
banks = new Dictionary<string, string> { { "swiss", "12500044000" }, { "camen", "12000000" } }
},
new Person
{
cars = new Dictionary<string, string> { { "volvo", "3554000" }, { "bmw", "50023200" } },
houses = new Dictionary<string, string> { { "mansion", "1006600000" },{ "cardboard box", "244" } },
banks = new Dictionary<string, string> { { "swiss", "125000544000" }, { "camen", "12000777000" } }
},
new Person
{
cars = new Dictionary<string, string> { { "volvo", "340050" }, { "bmw", "50545000" } },
houses = new Dictionary<string, string> { { "mansion", "100040000" },{ "cardboard box", "112" } },
banks = new Dictionary<string, string> { { "swiss", "12500330000" }, { "camen", "12000000" } }
}
};
Here's a nifty trick; basically, a Dictionary can be thought of as a List of KeyValuePair<> objects.
Dictionary<int, string> myDictionary = new Dictionary<int, string>();
foreach(var item in myDictionary)
// item is a KeyValuePair<int, string>, enumerated in order of their insertion into the dictionary
Now that it is in a list, it's easy to sort via LINQ:
Dictionary<int, string> sample = new Dictionary<int, string>
{
{ 1, "Sample" },
{ 2, "Another Sample" }
};
var orderedList = sample.OrderBy(x => x.Value).ToList();
Of course, the bigger problem is why you would need to sort and order a Dictionary - that's not exactly an operation that is really grouped with the concept of a dictionary (it's more for quick access of specific elements via a specified key). The problem description you write about seems odd; you can order the cars for a specific person, but are you trying to find each car from each person ordered by value?
That's easy to do as well:
List<PersonCarDetails> allStuff = new List<PersonCarDetails>();
foreach(var person in persons)
allStuff.AddRange(person.Cars.Select(x => new PersonCarDetails { PersonId = person.Id, CarName = x.Key, CarId = x.Value }).ToList());
// allStuff now contains a list of PersonCarDetails, and then you can order that:
var orderedList = allStuff.OrderBy(x => x.CarId).ToList();
If you mean sort by the number of cars owned by the person
var result = Person.OrderByDescending(x => x.cars.Count);
If you mean sort by the first (sorted by name) car name owned by the person
var result = Person.OrderByDescending(x => x.cars.Keys.OrderBy(y => y.Key).FirstOrDefault());
If you mean sort by the first (sorted by number) car number owned by the person
var result = Person.OrderByDescending(x => x.cars.Keys.OrderBy(y => y.value).FirstOrDefault());
An example output would be good to clarify what actually you want to sort by, since cars is a list, rather than just an element.
Based on the examples you provided this might just do the job for you:
var result = Person.OrderByDescending(x => x.cars.Values.FirstOrDefault());

Categories

Resources