Finding the "mode" of pairs of numbers - c#

My relevant code looks something like this:
//The object
Class MyClass
{
int PositionCount { get; set;}
Value { get; set;}
MyClass(int positionCount, double value)
{
PositionCount = positionCount;
Value = value;
}
}
//And then, later, using the object
List<MyClass> list = new List<MyClass>();
MyClass obj1 = new MyClass(18, 356.2);
list.Add(obj1);
MyClass obj2 = new MyClass(18, 356.2);
list.Add(obj2);
MyClass obj3 = new MyClass(19, 22.5);
list.Add(obj3);
MyClass obj4 = new MyClass(19, 30.325);
list.Add(obj4);
MyClass obj5 = new MyClass(19, 356.2);
list.Add(obj5);
What I'd like to find is the most common occurrence of number pairs in this list. Here, I'd expect to get back the values in obj1 and obj2, since they repeat two numbers each. I haven't had much luck with getting the modes of PositionCount and Value separately, as (in this case), the mode of PositionCount is 19 and Value is 356.2, but there is no pair (or more) of elements in the list with both of these numbers.
Thanks for any guidance.

Something like this:
var mostCommon = list
.GroupBy(x=>new {x.PositionCount, x.Value})
.OrderByDescending(x=>x.Count()).First();
It will group by your properties and then get that with biggest count

Related

Setting a Property via Reflection in a copied List updates original list

I'm experiencing a problem in my C# code and I'm sure it has to do with the way I'm using reflection, but I'm not sure how to fix it.
To the best of my knowledge, if I have:
List1 = List<MyClass>
and use a syntax similar to
List2 = new List<MyClass>(List1);
Then List2 should be a copy of List1 and any updates made to it should not reflect in the original list.
That being the case, consider the following test code:
public class Fake
{
public string MyVal { get; set; }
}
public List<Fake> List1;
public List<Fake> List2;
public void UpdateClassTest()
{
List1 = new List<Fake>() {new Fake() { MyVal = "hello" } };
List2 = new List<Fake>(List1);
string propName;
System.Type type = typeof(Fake);
foreach (System.Reflection.PropertyInfo pi in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
propName = pi.Name;
List2.ForEach(f => pi.SetValue(f, "Good Bye"));
}
}
When I run this Both List1[0] and List2[0] get updated to "Good Bye", but I would assume List1 would not be affected by the changes I'm making to List2.
What am I doing wrong or not understanding here?
new List(List other) does not do a deep copy. When you modify the item at [0] it's modifying the original object, which exists in both lists.
See this other question about implementing ICloneable.
Copying the list means that the lists are different objects. The elements contained by the lists are still the same. For instance:
List1 = new List<Fake>() {new Fake { MyVal = "hello" } };
List2 = new List<Fake>(List1);
List2.Add(new Fake { MyVal = "hey" });
Console.WriteLine(List1.Length); // 1
Console.WriteLine(List2.Length); // 2
List2[0].MyVal = "hi";
Console.WriteLine(List1[0].MyVal) // hi

Comparing two lists of nested lists and returning the added/changed/removed items

I've looked at many similar questions on stackoverflow, but I haven't seen an exact match for my problem.
I need to compare two "lists of nested lists" and capture the differences. One is an "old" list and the other is a "new" list. When comparing the nested lists, they can be considered equal if all of the NESTED list items (the MyObject.Ids) are present in both lists in order (you can assume that the nested MyObject.Ids lists are already sorted and that there are no duplicates). The MyObject.Id and MyObject.Name properties are not considering in the equality comparison, but they are still important metadata for MyObject's which should not get lost.
I am not looking for a boolean indicator of equality. Instead I need to create three new lists which capture the differences between the old and new lists (e.g. a list of items which were Added, a list of items which were Removed, and a list of items which were present in both lists).
Below is an example of some code which does exactly what I want! What I would like to know is how to make this shorter/better/simpler (cutting out one of the for loops would be a good start). To make things trickier, please assume that you cannot make any changes to the MyObject class or use any custom Equals/IEqualityComparer etc implementations.
public class MyObject
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<Guid> Ids { get; set; }
}
...
// Get the list of existing objects (assume this returns some populated list)
List<MyObject> existingObjects = GetExistingObjects();
// Create a list of updated objects
List<MyObject> updatedObjects = new List<MyObject>()
{
new MyObject()
{
Ids = new List<Guid>() { new Guid("48af3cb9-945a-4ab9-91e4-7ee5765e5304"), new Guid("54b5128a-cf53-436c-9d88-2ef7abd15140") }
},
new MyObject()
{
Ids = new List<Guid>() { new Guid("0485382f-8f92-4a71-9eba-09831392ceb9"), new Guid("3d8b98df-caee-41ce-b802-2f0c5f9742de") }
}
};
// Do the comparison and capture the differences
List<MyObject> addedObjects = new List<MyObject>();
List<MyObject> removedObjects = new List<MyObject>();
List<MyObject> sameObjects = new List<MyObject>();
foreach (MyObject obj in updatedObjects)
{
if (existingObjects.Any(list => list.Ids.SequenceEqual(obj.Ids)))
{
sameObjects.Add(obj);
continue;
}
addedObjects.Add(obj);
}
foreach (MyObject obj in existingObjects)
{
if (!updatedObjects.Any(list => list.Ids.SequenceEqual(obj.Ids)))
{
removedObjects.Add(obj);
}
}
Here is a little shorter (due to elimination of the second loop) and little better (due to elimination of the ineffective search contained in the second loop). Still O(N^2) time complexity due to ineffective search contained in the loop though.
var addedObjects = new List<MyObject>();
var removedObjects = new List<MyObject>(existingObjects);
var sameObjects = new List<MyObject>();
foreach (var newObject in updatedObjects)
{
int index = removedObjects.FindIndex(oldObject => oldObject.Ids.SequenceEqual(newObject.Ids));
if (index < 0)
addedObjects.Add(newObject);
else
{
removedObjects.RemoveAt(index);
sameObjects.Add(newObject);
}
}
Update: A shorter, but IMO definitely not better (in fact worse performance wise) version
var addedObjects = updatedObjects.Where(newObject => !existingObjects.Any(oldObject => oldObject.Ids.SequenceEqual(newObject.Ids))).ToList();
var removedObjects = existingObjects.Where(oldObject => !updatedObjects.Any(newObject => newObject.Ids.SequenceEqual(oldObject.Ids))).ToList();
var sameObjects = updatedObjects.Where(newObject => !addedObjects.Any(addedObject => addedObject.Ids.SequenceEqual(newObject.Ids))).ToList();
If MyObject does not define custom equality comparison, i.e. uses default reference equality, the last line could be replaced with shorter and better performing
var sameObjects = updatedObjects.Except(addedObjects);
You can use Intersect and Except function in Linq
With Intersect you will get existing object,
and with Except you will get new objects.
Example of Except from MSDN:
double[] numbers1 = { 2.0, 2.1, 2.2, 2.3, 2.4, 2.5 };
double[] numbers2 = { 2.2 };
IEnumerable<double> onlyInFirstSet = numbers1.Except(numbers2);
foreach (double number in onlyInFirstSet)
Console.WriteLine(number);

C# remove null values from object array

I got an array of a specific object. Lets say the object Car. At some point in my code I need to remove all Car-objects from this array that do not fulfill the requirements I stated. This leaves null values in the array.
public class Car{
public string type { get; set; }
public Car(string ntype){
this.type = ntype;
}
}
Car[] cars = new Car[]{ new Car("Mercedes"), new Car("BMW"), new Car("Opel");
//This should function remove all cars from the array where type is BMW.
cars = removeAllBMWs(cars);
//Now Cars has become this.
Cars[0] -> Car.type = Mercedes
Cars[1] -> null
Cars[2] -> Car.type = Opel
//I want it to become this.
Cars[0] -> Car.type = Mercedes
Cars[1] -> Car.type = Opel
Of course my real code is far more complex than this, but the base idea is the same. My question that I have is: How can I remove the empty values from this array?
I found countless solutions for a string array, but none for an object array.
The following will create a new array with all the null values excluded (which seems to be what you actually want?):
Cars = Cars.Where(c => c != null).ToArray();
Better yet, define your RemoveAllBMWs method to omit the BMWs in the first place instead of setting them to null:
internal static Car[] RemoveAllBMWs(IEnumerable<Car> cars)
{
return cars.Where(c => c != null && c.Type != "BMW").ToArray();
}

How to unchain items in list<t> class

can some one explain to me how to break the chain with a NEW statement?
Let me clarify the chain I’m talking about. When I call to a class I use the NEW statement like so
Myclass x =new Myclass();
My understanding is this creates a new empty instance of Myclass. Now correct me if I’m wrong but having a new empty instance one should be able to add what ever data the class supports?
I use this lot and would think the above to be true until adding data in such a manner
Myclass x =new Myclass();
//oldMyclass being old data that needs to be changed then
//added back to the class as a new or duplicate entry
x = oldMyclass[1];
//we change the data
x.red= 0x54;
//we add it back
oldMyclass.add(x);
All is good until we edit the data after adding it say we need to change another value.
We access the oldMyclass and select the proper item say its index is 2 but we only want to change the values of index 2
Myclass x =new Myclass();
x = oldMyclass[2];
x.red=soemvalue;
oldMyclass[2] = x;
This will change the red value of both index 1 and index 2. How can I break the chain between index 1 and index 2?
I think I might have over simplified this question let me know.
Thanks for any information.
Edit: Here is the copy method that I tried
public static Items.SavedItem Copy(Items.SavedItem old)
{
Items.SavedItem x = new Items.SavedItem();
x.generator = old.generator;
x.hireling_class = old.hireling_class;
x.id = old.id;
x.item_slot = old.item_slot;
x.owner_entity_id = old.owner_entity_id;
x.socket_id = old.socket_id;
x.square_index = old.square_index;
x.used_socket_count = old.used_socket_count;
return x;
}
So let's say, for arguments sake, you have a class like this:
public MyClass
{
public string Foo { get; set; }
}
And you have a collection
List<MyClass> myList = new List<MyClass>();
Now you create an instance of MyClass
MyClass obj1 = new MyClass() { Foo = "bar" };
Now if you do this:
myList.Add(obj1);
myList.Add(obj1);
You now have a list with TWO members, but they happen to be the same object. Whats stored in the list is a reference to the object you added, not the object itself. So myList[0] == myList[1]
Now if you did this:
MyClass item = myList[1];
And then:
item.Foo = "something else";
Both the item at index 1 and the item at index 0 will have 'Foo == "something else"' because they are the same item.
Another point that seems to be confusing you is this: myList has two items. If I do this:
MyClass item = myList[0];
myList still has two items. Indexing a collection doesn't remove it and because of that, there is no need to add the item back to the list. It's already there. All I've done is copy the reference from myList to a variable named item.
There are collections (Stack and Queue for example) that do work on the principle that you will remove items and (potentially) add them back, but List doesn't work that way.
So if you wanted to add multiple objects to myList you need to create multiple objects with the new keyword. For example:
List<MyClass> myList = new List<MyClass>();
MyClass obj1 = new MyClass() { Foo = "bar" };
myList.Add(obj1);
obj1 = new MyClass() { Foo = "something else" }; // Note: I've reused the variable, but this is a *new* object
myList.Add(obj1);
Or, if you don't need the new object assigned to a variable, you can simply if to:
List<MyClass> myList = new List<MyClass>();
myList.Add(new MyClass() { Foo = "a" });
myList.Add(new MyClass() { Foo = "b" });
Or even more compactly, you can exploit the collection initialization syntax and simply:
List<MyClass> myList = new List<MyClass>()
{
new MyClass() { Foo = "a" },
new MyClass() { Foo = "b" }
}
If you want to copy an object from your list, then you need to copy each property (and if it contains other objects, you may need to copy them too). There are various ways to do this, IClonable or a copy constructor are examples, but it basically comes down to, at some point, doing something like this:
myCopy.Foo = myOriginal.Foo;
myCopy.Bar = myOriginal.Bar;
// repeat for all properties that you want to copy.
Now assuming that Foo and Bar aren't also reference types, you have a copy. If they are reference types, you have a copy, but myCopy.Foo and myOriginal.Foo are still pointing at the same object.

Sorting an Object List, on a user defined property with c#

I have an Object (Called MyReading) with 18 properties.
I add instances of this Object to a List
eg:
List<MyReading> MyReadingsL = new List<MyReading>();
MyReading O1 = new MyReading();
O1._DateTime = "10";
O1._Value1 = "Hello1";
O1._Value2 = "Hello2";
O1._Value3 = "Hello3";
O1._Value4 = "Hello4";
....etc
MyReadingsL.Add(O1);
I need to sort the list of readings by any one of the 18 properties. (The user decides which ones)
I understand i must write a delegate for the Sort() method of the list, to specify my own comparison logic in code.
eg. MyReadingsL.Sort(TheDelegate);
Problem is, i do not want to write 18 delegates for each property that i can probably sort on.
Maybe one delegate, a (Comparison Delegate) accepting (MyReading x, MyReading y) , and a string, that indicates the property to be sorted on.
How is this possible?
Very easy. Linq already gives you this:
MyReadingsL.OrderBy(r => r._Value1);
MyReadingsL.OrderBy(r => r._Value2);
...
MyReadingsL.OrderBy(r => r._Valuen);
...
If you want to define an external function that you call in the same way, your signature should look like this:
public IEnumerable<MyReading> GetSortedList(Func<MyReading, string> property) { }
To translate from a string into a property, you can define a static data member.
public static IDictionary<string, Func<MyReading, string>> Properties =
typeof(MyReading).GetProperties().ToDictionary(p => prop.Name, p => new Func<MyReading, string>(r => p.GetValue(r)));
This static member gives you a dictionary of all the properties in your class, keyed by their identifying strings and giving you access to the delegates that let you perform the Linq operations you need.
Then, given a string s that identifies a property, you can call MyReadingsL.OrderBy(Properties[s]) at very little cost.
You can achieve that by linq. What you'll have to do is pass the string/property you'll want to sort with, and then use the orderby.
General example:
// Create 10 objects with 2 properties
var num_and_name_list =
from num in Enumerable.Range(1,10)
select new { val=num, name=(""+num+"oeu")};
// Here i'll sort them by the name property.
var sorted_by_name_list =
from some_object in num_and_name_list
orderby some_object.name descending
select some_object;
The results will look like
So, you'll just have to see how / where you pass your property to sort with.
If you need to get the property from the string, you could do something like:
// Create 10 objects with 3 properties
var num_and_name_list =
from num in Enumerable.Range(1, 10)
select new ExtraStringDataPoint ( num, num*2, ("" + num + "oeu"));
// Hunting your property starts
Type myType = num_and_name_list.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());
PropertyInfo order_on_this = null;
foreach (PropertyInfo prop in props)
{
order_on_this = typeof(ExtraStringDataPoint).GetProperty("Y");
}
// Here i'll sort them by the name property.
var sorted_by_name_list =
from some_object in num_and_name_list
orderby order_on_this descending
select some_object;
My ExtraStringDataPoint looks like:
public class ExtraStringDataPoint : IDataPoint
{
public ExtraStringDataPoint(double x, double y, string s)
{
X = x;
Y = y;
Extra = s;
}
public double X { get; set; }
public double Y { get; set; }
public string Extra { get; set; }
public override string ToString()
{
return X +" , " + Y + " , " + Extra;
}
}
In your case , you can just pass the variable you want as a string, like I used "Y".

Categories

Resources