I have a class:
public class ItemObject : ScriptableObject
{
int id;
string name;
}
and I can sort them by their id like this:
sortedItems = new List<GameObject>(allItems.OrderBy(x => x.GetComponent<InventorySlotItem>().item.id));
but I also have the child class:
public class EquipmentObject : ItemObject
{
int power;
int def;
int spDef;
}
is there a way to use the OrderBy method for sorting them by "power" ? I was hoping for some downcasting like:
sortedItems = new List<GameObject>(allItems.OrderBy(x => (EquipmentObject)x.GetComponent<InventorySlotItem>().item.power));
I tried to downcast in many different ways but nothing worked.
Related
I want to pass a string in the LINQ query.
string TableName = "db.Countries";
var ActualData = (from n in TableName
where n.Record_Instance >= 0
select n).OrderBy(primaryColumn);
My aim behind this is; I want to put the query in a method and call it whenever I need it. Basically changing the TableName and passing it as a parameter on function call.
Is there a way to do this?
Update :
Workaround :
var TableName = db.Countries;
GetConditionaldata(TableName,..);
private object GetConditionaldata( DbSet<Country> TableName, ..)
{
var ConditionalData = (from n in TableName
where n.Record_Instance >= 0
select n).OrderBy(primaryColumn);
var count = ConditionalData.Count();
var countries = ConditionalData.Skip(jtStartIndex).Take(jtPageSize);
return countries;
}
But Here, I want have to again specify DbSet<Country> as the parameter type. If I can at least find a way to get a Generic Dbset<> Which I can pass on as parameter type for my tableName, then my problem would be solved.
Assuming you have multiple entities containing the same property that you want to execute the same query on, then you can introduce an interface:
public interface IInstanceRecord
{
int Record_Instance { get; set; }
}
Then apply it to your entities in partial classes (or directly if using Code First):
public partial class Country : IInstanceRecord { }
public partial class Foo : IInstanceRecord { }
public partial class Bar : IInstanceRecord { }
Now you can make your method generic, and add a constraint that the generic types it operates on must implement IInstanceRecord:
public IQueryable<T> GetConditionalData<T>(IQueryable<T> dbSet, ...)
where T : IInstanceRecord
{
var conditionalData = (from n in dbSet
where n.Record_Instance >= 0
select n).OrderBy(primaryColumn);
var count = conditionalData.Count();
var filteredData = conditionalData.Skip(jtStartIndex).Take(jtPageSize);
return filteredData;
}
And call it with whatever DbSet<T> (or other IQueryable<T>) you want, as long as T : IInstanceRecord:
var filteredCountries = GetConditionalData(dbContext.Countries);
var filteredFoos = GetConditionalData(dbContext.Foos);
var filteredBars = GetConditionalData(dbContext.Bars);
I'm trying to convert a list of objects to a dictionary using the following code:
var MyDictionary = MyList.Distinct().ToDictionary(i => i.ObjectId, i => i);
I know that a dictionary should not contain duplicate elements, hence the .Distinct(). Yet I still get the following Exception whenever there's a duplicate element:
An item with the same key has already been added.
MyList is a list of MyObject that looks like this:
public class MyObject{
public string ObjectId { get; set; }
public string FName { get; set; }
public string LName { get; set; }
}
Is there a better way to create a dictionary from a list of objects ? or am I doing something wrong?
If you want to compare on the ObjectId, you'll need to pass in a custom comparer to .Distinct(). You can do so like this:
class MyObjectComparer : IEqualityComparer<MyObject>
{
public bool Equals(MyObject x, MyObject y)
{
return x.ObjectId == y.ObjectId;
}
public int GetHashCode(MyObject obj)
{
return obj.ObjectId.GetHashCode();
}
}
var MyDictionary = MyList
.Distinct(new MyObjectComparer())
.ToDictionary(i => i.ObjectId, i => i);
You could use Group by and then select first from the List as below:
var MyDictionary = MyList.GroupBy(i => i.ObjectId, i => i).ToDictionary(i => i.Key, i => i.First());
Distinct works using the objects built in Equals and GetHashCode methods by default but your dictionary works only over the id. You need to pass in a IEqualityComparer in to distinct that does the comparison on Id to test if items are equal or make MyObject implment Equals and GetHashCode and have that compare on the Id.
I'm a newb so I apologize if this is a dumb question. I have bound my interface to the fields of a class I built. I initiated class as a List of type T, now I am trying to increment the assignment of fields to an index of the list.
My code looks something like this.
my class:
class MyClass
{
public string ID { get; set; } // I want these to increment
public string MyVar { get; set; }
public MyClass()
{
this.ID = "";
this.MyVar = "";
}
public MyClass (string id, string myvar)
{
this.ID = id;
this.MyVar = myvar
}
public static List<MyClass> Query(string datasource)
{
XElement data = XElement.Load(datasource);
List<MyQuiz> query = (from d in data.Descendants("Object")
select new MyQuiz((string)d.Element("ID"),
(string)d.Element("MyVar")
)).ToList();
return query;
}
public static List<MyClass> Assign (List<MyClass> assign, int i)
{
i++
//Can't do this because it's static, need another way!
this.ID = assign[i].ID;
this.MyVar = assign[i].MyVar;
}
The initiating code
int i = 0;
List<MyClass> myClass = new List<MyClass>();
myClass = MyClass.Query("data.xml");
MyClass.Assign(myClass, i);
and the xml
<root>
<Object>
<ID>1</ID>
<MyVar>TESTING</MyVar>
</Object>
<root>
Everything works except the Assign method, any suggestions?
If your type has a state it will be better to create an instance of this class before using it.
Just remove static keywords from the methods and then use the following code:
List<MyClass> myClass = new List<MyClass>();
MyClass myClassInstance = new MyClass();
myClass = myClassInstance.Query("data.xml");
myClassInstance.Assign(myClass, i);
It looks like you're trying to do something like this:
public static List<MyClass> Assign (MyClass target, List<MyClass> assign, int i)
{
i++;
target.ID = assign[i].ID;
target.MyVar = assign[i].MyVar;
}
Which will replace the values in the first instance of MyClass with the ones in the i'th instance of your List<MyClass>
It's a tad hard to tell though because it's not obvious what you're trying to achieve here. It doesn't look like there's any reason not to just re-instantiate the object with the new parameters.
I guess you want to initialize the Id:
public static List<MyClass> Assign (List<MyClass> assign, int i)
{
for(int j=0;j<assign.Count;j++){
assign[j].ID = i;
i++
}
}
public static List<MyClass> myClassList = new List<MyClass>();
public static List<MyClass> Assign (List<MyQuiz> assign, int i)
{
myClassList.Add(new MyClass(assign[i].ID, assign[i].MyVar));
return myClassList;
}
Based on your question, this is what you're looking for. Create a new instance of MyClass, add it to the list, and assign field values based on i.
Edit: Added a public static list of MyClass to your class. This should add the item to a new static list in the class and return the list. It's unclear since there are two class names in the question and seem to be some type issues in the code.
I have a List<MyClass> someList.
class MyClass
{
public int Prop1...
public int Prop2...
public int Prop3...
}
I would like to know how to get a new distinct List<MyClass> distinctList from List<MyClass> someList, but only comparing it to Prop2.
You can emulate the effect of DistinctBy using GroupBy and then just using the first entry in each group. Might be a bit slower that the other implementations though.
someList.GroupBy(elem=>elem.Prop2).Select(group=>group.First());
Unfortunately there's no really easy built-in support for this in the framework - but you can use the DistinctBy implementation I have in MoreLINQ.
You'd use:
var distinctList = someList.DistinctBy(x => x.Prop2).ToList();
(You can take just the DistinctBy implementation. If you'd rather use a Microsoft implementation, I believe there's something similar in the System.Interactive assembly of Reactive Extensions.)
you need to use .Distinct(..); extension method.
Here's a quick sample:
public class Comparer : IEqualityComparer<Point>
{
public bool Equals(Point x, Point y)
{
return x.X == y.X;
}
public int GetHashCode(Point obj)
{
return (int)obj.X;
}
}
Do not forget about GetHashCode.
Usage:
List<Point> p = new List<Point>();
// add items
p.Distinct(new Comparer());
Override Equals(object obj) and GetHashCode() methods:
class MyClass
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
public int Prop3 { get; set; }
public override bool Equals(object obj)
{
return ((MyClass)obj).Prop2 == Prop2;
}
public override int GetHashCode()
{
return Prop2.GetHashCode();
}
}
and then just call:
List<MyClass> distinctList = someList.Distinct().ToList();
Since the introduction of value tuples, if you want a LINQ equivalent to SQL's DISTINCT
items.GroupBy(item => (item.prop1, item.prop2, ...)).Select(group => group.First())
If you would like to Distinct your list by multiple fields, You have to create an instance of IEqualityComparer interface:
public class MyComparer : IEqualityComparer<MyModel>
{
public bool Equals(MyModel x, MyModel y)
{
// compare multiple fields
return
x.Field1 == y.Field1 &&
x.Field2 == y.Field2 &&
x.Field3 == y.Field3 ;
}
public int GetHashCode(MyModel obj)
{
return
obj.Field1.GetHashCode() +
obj.Field2.GetHashCode() +
obj.Field3.GetHashCode();
}
}
Then use the comparer to distinct your list:
var distinctedList = myList.Distinct(new MyComparer()).ToList();
I know it's been a while, but I needed the simplest answer and at this time (with .NET 4.5.1) I found the following to be the most straight-forward answer I could get to:
IEnumerable<long> allIds = waitingFiles.Values.Select(wf => wf.groupId).Distinct();
My situation is that I have a ConcurrentDictionary that looks something like:
ConcurrentDictionary<long, FileModel>
The ConcurrentDictionary Values property is basically my List<FileModel>.
*FileModel has a groupId that isn't necessarily unique (though, obviously the key (long) that I use to add the FileModel object into the dictionary is unique to the FileModel).
*Named for clarity in the example.
The point is that I have a large number of FileModels (imagine 100) in the ConcurrentDictionary and within those 100 FileModels there are 5 different groupIds.
At this point I just need a list of the distinct groupId.
So, again if I just had a list of FileModel the code would look like the following:
IEnumerable <long> allIds = allFileModel.Select(fm => fm.groupId).Distinct();
I have a list where i want the type to be definined by the call for example in the class i want something like
public class ClassName
{
public ListType<T> ListName { get; set; }
// other class items
}
and then the usage to be what sets the class type like
var className = new ClassName()
{
ListType<int> = data
};
so basically thats what i want, i have it working using dynamic so the class is
public class ClassName
{
public ListType<dynamic> ListName { get; set; }
// other class items
}
and the call is
var className = new ClassName()
{
ListType<dynamic> = data
};
this works but i would like to know if there is a better way to do this so i dont have to use dynamic
oh almost forgot to mention the ListType is
public class ListType<T> : List<T>
{
}
and so doesnt fail by having different types passed to it
thanks
edit:
realised my usage of the code on stack overflow differed from my code
the ListType has a constructor that takes 3 arguments so the usage is more
var className = new ClassName()
{
ListName = new ListType<Type>(x, y, z)
}
How about
public class ClassName<T>
{
public ListType<T> ListName { get; set; }
// other class items
}
then use it like this:
var className = new ClassName<int>()
{
ListName = data;
};
Slight addition to Bertrand's answer gives you a way to not repeat the type argument in you specific use case, or even not mention it:
public static class ClassName
{
public static ClassName<T> Create<T>(ListType<T> list)
{
return new ClassName<T> { ListName = list };
}
public static ClassName<T> Create<T>(params T[] list)
{
return new ClassName<T> { ListName = new ListType<T>(list) };
}
}
Using the first method, you can write something like
ClassName.Create(new ListType<SomeType>(x, y, z));
using the second method, you can even write
ClassName.Create(x, y, z);
and let the compiler figure out that T is SomeType, but that doesn't work always.
Note that ClassName is different class than ClassName<T> and you might want to name it differently, e.g. ClassNameFactory.