Sum on a dynamic list that has ExpandoObject as items - c#

I have a dynamic list with ExpandoObject as items :
List<dynamic> list = new List<dynamic>();
foreach (...)
{
var dynamicObject = new ExpandoObject() as IDictionary<string, Object>;
...
list.Add(dynamicObject);
}
How can I use .Sum() on a dynamic list ? I know the names of the properties
of that list , but Sum() does not take a string as argument .
Thanks

Assuming you have list like this:
var list = new List<dynamic>
{
new ExpandoObject(),
new ExpandoObject(),
new ExpandoObject(),
};
list[0].Foo = 1;
list[1].Foo = 2;
list[2].Foo = 3;
you can use ExpandoObject's properties as regular properties, if their names are known at compile-time:
var sum1 = list
.Sum(item => item.Foo);
or use dictionary syntax, if property names are known at run-time only:
var sum2 = list
.Sum(item => (int)((IDictionary<string, object>)item)["Foo"]);

You can use Sum(Func<TSource, int> selector)
For you example :
var values = new int[] {1, 2, 3, 4, 5};
List<dynamic> list = new List<dynamic>();
foreach (var value in values)
{
var dynamicObject = new ExpandoObject() as IDictionary<string, Object>;
dynamicObject[value.ToString()] = value;
list.Add(dynamicObject);
}
// Kind of ugly as cast but otherwise it has trouble to find the Count property
var result = list.Sum(x => (x as IDictionary<string, Object>).Count);
Console.WriteLine("Result: {0}", result);
Console.ReadLine();

To my mind you could try this :
var listSum = list.Sum(item => item.GetType().GetProperty("propertyName").GetValue());
I called list the list on which you want to call the Sum method.
Let me know if the result is what you want.

Related

How to print the duplicates value while converting from Dictionary to List in c#

I am trying to converting from dictionary to list while converting I am getting the output
I/p-
dic.Add("Demo1",2);
dic.Add("Demo2",1);
dic.Add("Demo3",1);
dic.Add("Demo4",2);
O/p-
Demo1
Demo2
Demo3
Demo4
But I need Demo1 and Demo4 two times because their quantity are 2. So How can I achieve that??
Below is the code
public IList<string> DictionaryToList(IDictionary<string,int> dictionary)
{
IDictionary<string, int> dic = new Dictionary<string, int>();
IList<string> lst = new List<string>();
dic.Add("Demo1",2);
dic.Add("Demo2",1);
dic.Add("Demo3",1);
dic.Add("Demo4",2);
foreach (var item in dic)
{
if (!lst.Contains(item.Key))
{
lst.Add(item.Key);
}
}
return lst;
}
}
class Program
{
static void Main(string[] args)
{
var conversion = new Conversion();
var list = new List<string> { "Demo1","Demo2","Demo3","Demo4","Demo1","Demo4"};
var dictionary = conversion.ListToDictionary(list);
foreach (var item in dictionary)
{
Console.WriteLine($"{item.Key}, {item.Value}");
}
var convertedList = conversion.DictionaryToList(dictionary);
foreach (var item in convertedList)
{
Console.WriteLine($"{item}");
}
Console.ReadLine();
}
Thanks in advance.
You can use LINQ's SelectMany and Enumerable.Repeat:
IList<string> list = dictionary
.SelectMany(kv => Enumerable.Repeat(kv.Key, kv.Value))
.ToList();
Here is also the opposite way to build your dictionary from the list:
var list = new List<string> { "Demo1", "Demo2", "Demo3", "Demo4", "Demo1", "Demo4" };
var dictionary = list.GroupBy(s => s).ToDictionary(g => g.Key, g => g.Count());
IList<string> list2 = dictionary
.SelectMany(kv => Enumerable.Repeat(kv.Key, kv.Value))
.ToList();
So at the end list2 contains the same strings as list but in a different order.
Your dictionary consists of a key (string) and a value (int). After checking
if (!list.Contains(item.Key)) just add another loop which goes from 0 to the actual value from your dictionary-item and adds the new item n-times.
for (int i = 0; i < item.Value; i++) // Demo1 and Demo4 runs 2x, Demo2 and Demo3 1x
lst.Add(item.Key);
Do you want something like this?
Dictionary<string, int> dic = new Dictionary<string, int>();
List<string> lst = new List<string>();
dic.Add("Demo1", 2);
dic.Add("Demo2", 1);
dic.Add("Demo3", 1);
dic.Add("Demo4", 2);
foreach (var item in dic)
{
for (int i = 0; i < item.Value; i++)
{
lst.Add(item.Key);
}
}

arraylist with object type

hi i using arraylist and storing simple object array in that , my sample code snipt
ArrayList rows = new ArrayList();
object[] objs = new object[3];
objs[0] = 1;
objs[1] = "dilip";
objs[2] = 27;
rows.Add(objs);
objs = new object[3];
objs[0] = 2;
objs[1] = "lucky";
objs[2] = 42;
rows.Add(objs);
objs = new object[3];
objs[0] = 3;
objs[1] = "user";
objs[2] = 46;
rows.Add(objs);
objs = new object[3];
objs[0] = 4;
objs[1] = "testing";
objs[2] = 76;
rows.Add(objs);
objs = new object[3];
objs[0] = 5;
objs[1] = "trying";
objs[2] = 44;
rows.Add(objs);
How can i apply asc or desc sorting on any index of object
for example sorting based on name which index 1 or sorting based on age which index 2 ..
please provide any suggestion .
Thanks ..
Most of LINQ methods will work with a strongly typed IEnumerable<T> interface.
Use OfType method like this rows.OfType<object[]>().OrderBy(x => x[1])
Though the way you approach your data structures will quickly make the code unmaintainable. You'd better consider using classes to reflect your data.
You need to have comparer to sort your ArrayList type. In your case it would look something like this:
public class MyComparer : IComparer
{
int IComparer.Compare(Object x, Object y)
{
int sortingIndex = 1;
var xUnbox = x as object[];
var yUnbox = y as object[];
return ((new CaseInsensitiveComparer()).Compare(yUnbox[sortingIndex], xUnbox[sortingIndex]));
}
}
Having this, you can now sort your ArrayList:
var comparer = new MyComparer();
rows.Sort(comparer);
foreach (object[] line in rows)
{
Console.WriteLine(line[1]);
}
This example would sort your ArrayList by index 1.
Although I would highly recommend using strongly typed collection, like List<YourType> instead, since then you could just Linq order that.
Is there a reason you could not use List<object[]> instead of using ArrayList?
For example:
List<object[]> rows = new List<object[]>();
object[] objs = new object[3];
objs[0] = 1;
objs[1] = "dilip";
objs[2] = 27;
rows.Add(objs);
var query = rows.Where(r => (string)r[1] == "dilip");
You could then do all your various sorting, etc.
var query = rows
.OrderBy(r => (int)r[0])
.OrderBy(r => (string)r[1])
.OrderByDescending(r => (int)r[2]);

Lambda expression to loop through two concurrent dictionaries

I am trying to loop through two concurrent dictionaries like the code below, however I want to use a lambda expression instead
foreach (var s in sb_eventdata)
{
foreach (var f in final_data)
{
if (s.Value.Car.Equals(f.Value.Car))
{
Console.Writeline("Found!");
}
}
}
var values = sb_eventdata.Where(k => k.Value.Hometeam.Contains( ???? );
I'm really not sure what to pass into contains, I assume another lambda expression but what?
The closest linq expression to your loops would be:
var sb_eventdata = new Dictionary<string, string>{ {"a", "a"}, {"b", "b"}};
var final_data = new Dictionary<string, string>{{"a", "a"}, {"b", "b"}, {"c","c"}};
var result =
// first loop
sb_eventdata.Select(s =>
// second loop
final_data.Where(f => s.Value.Equals(f.Value)))
// flatten results (returns results from the first dictionary)
.SelectMany(x => x);
You can use a linq Intersect function to find like items in a list.
Then display all like items.
var foo = sb_eventdata.Select(o => o.Value.Car).Intersect(final_data.Select(o => o.Value.Car));
foreach (var item in foo)
{
Console.Writeline("Found!");
}
I think your friend is the Join() method.
In "LinqPad style":
void Main()
{
var a = new[] {
new Car("Opel",200),
new Car("Volkswagen",300),
new Car("Audi", 500)
};
var b = new[] {
new Car("Peugeot", 180),
new Car("Seat", 300),
new Car("Volvo", 480)
};
var c = a.Join(b, ak => ak.Value, bk => bk.Value, (ak,bk) => new {A=ak.Name,B=bk.Name,ak.Value});
c.Dump();
}
// Define other methods and classes here
class Car {
public string Name;
public int Value;
public Car (string name, int value) {
Name = name;
Value = value;
}
}
If you just want to know if both dictionary share at least one value, you can use Any:
if(sb_eventdata.Any(s =>
final_data.Any(f => s.Value.Car.Equals(f.Value.Car))))
Console.WriteLine("Found!");
or with Contains:
if(sb_eventdata.Any(s => final_data.ContainsValue(s.Value)))
Console.WriteLine("Found!");
and if you want to count how many of sb_eventdata are in final_data:
sb_eventdata.Where(s => final_data.ContainsValue(s.Value)).Count();

C# Ordering 2 lists randomly

I have been trying to figure out how to randomly order two lists the same eg.
List<string> list = new List<string>();
list.Add("RedHat");
list.Add("BlueHat");
list.Add("YellowHat");
List<image> list2 = new List<image>();
list.Add(Properties.Resources.RedHat);
list.Add(Properties.Resources.BlueHat);
list.Add(Properties.Resources.YellowHat);
now if i wanted to order these so that redhat and the redhat image stay aligned how may i do this?And is there a way to combine these lists and then shuffle using a dictionary or keyvalue pair or something along those lines?
Wrap the two in an object:
class WrapperObject {
public string Name { get; set; }
public object Resource { get; set; }
}
Add them to a list:
var list = new List<WrapperObject>();
list.Add(new WrapperObject() {
Name = "RedHat",
Resource = Properties.Resources.RedHat
});
..randomize:
var rnd = new Random();
list = list.OrderBy(x => rnd.Next(50)).ToList();
Any specific reason why you want them in two lists, you could just create a list of keyvaluepairs like this:
var list = new List<KeyValuePair<string, image>> ();
list.Add(new KeyValuePair<string, image>("RedHat", (Properties.Resources.RedHat)));
list.Add(new KeyValuePair<string, image>("BlueHat", (Properties.Resources.BlueHat)));
list.Add(new KeyValuePair<string, image>("YellowHat", (Properties.Resources.YellowHat)));
You could store the data in a Tuple<,> but if you had more than 2 elements its worth just creating an explicit class to store the data.
Tuple example:
List<Tuple<string, image>> list = new List<Tuple<string, image>>();
list.Add(new Tuple<string,image>("RedHat", Properties.Resources.RedHat));
// etc...
LINQ-fu version:
var rng = new Random();
var res = Enumerable.Zip(list, list2, (e1, e2) => new { e1, e2 })
.OrderBy(x => rng.Next())
.Aggregate(new { list1 = new List<string>(), list2 = new List<image>() },
(lists, next) =>
{
lists.list1.Add(next.e1);
lists.list2.Add(next.e2);
return lists;
});
list = res.list1;
list2 = res.list2;
The following code should do what you want:
var list1 = new List<string>
{
"RedHat",
"BlueHat",
"YellowHat"
};
var list2 = new List<int>
{
1,
2,
3
};
var combined = list1.Zip(list2, (a, b) => new { a, b }).Shuffle(new Random()).ToList();
list1 = combined.Select(i => i.a).ToList();
list2 = combined.Select(i => i.b).ToList();
You'll need the following extension method:
public static class ShuffleExtension
{
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
T[] elements = source.ToArray();
for (int i = elements.Length - 1; i >= 0; i--)
{
int swapIndex = rng.Next(i + 1);
yield return elements[swapIndex];
elements[swapIndex] = elements[i];
}
}
}
First put the corresponding elements together, then apply random order:
var rnd = new Random();
var ordered = list.Zip(list2, Tuple.Create).OrderBy(el => rnd.Next()).ToArray();
You can easily extract back the individual lists, if needed:
var ordered_list = ordered.Select(tuple => tuple.Item1).ToList();
var ordered_list2 = ordered.Select(tuple => tuple.Item2).ToList();

Generate a new list with key

i would like to create a new list with key and values
List<object> r = new List<object>();
r.Add("apple");
r.Add("John");
return r;
when u Addwatch the r, you will see
[1] = apple
[2] = John
Questions: How do i make the [1] and [2] to be new key? When i addwatch the r, i would like to see [1] is replaced by Name. something as below:
Name = apple
TeacherName = John
Do you mean you want to use something like Dictionary<TKey, TValue>
example:
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("Name", "Apple");
d.Add("Teacher", "John");
or do you want an object to more strongly typed?
in this case you have to use your one class / struct
class MyObject
{
public string Name {get; set;}
public string Teacher {get; set;}
}
Then
var list = new List<MyObject>();
list.Add(new MyObject { Name = "Apple", Teacher = "John" });
list.Add(new MyObject { Name = "Banana", Teacher = "Setphan" });
then you can all it
var item = list[0];
var name = item.Name;
var teacher = item.Teacher;
It is completely incorrect to use a list for this kind of a data structure. You need to use use Dictionary , NameValueCollection or similar type.
You can transform your list:
List<object> r = new List<object>();
r.Add("apple");
r.Add("John");
r.Add("orange");
r.Add("Bob");
var dict = r.Where((o, i) => i % 2 == 0)
.Zip(r.Where((o, i) => i % 2 != 0), (a, b) => new { Name = a.ToString(), TeacherName = b.ToString() });
foreach (var item in dict)
{
Console.WriteLine(item);
}
Output:
{ Name = apple, TeacherName = John }
{ Name = orange, TeacherName = Bob }
And then transform to dictionary:
var result = dict.ToDictionary(d => d.Name, d => d.TeacherName);
You will need to use a Dictionary to do this. Not a List.
See http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
I hope i dont make any syntax mistakes here...
Dictionary <string, int> r = new Dictionary<string,int>();
r.add("apple",1);
r.add("John",2)
console.WriteLine(r["apple"]);//returns value 1
Your question is not clear and hard to understand.
Do you mean to say you want keys instead of indexes ? Like Name instead of 1
Well then as Aliza and Bumble Bee have said you need to use a Dictionary instead of a List.
Here's a small example
IDictionary<string, Interval> store = new Dictionary<string, string>();
store.Add("Name","apple");
store.Add("TeacherName ", John);
foreach(KeyValuePair<string, string> e in store)
Console.WriteLine("{0} => {1}", e.Key, e.Value);

Categories

Resources