Trying to use .remove to remove stuff from my List.. but it's not working, giving me the error "Argument type 'string' is not assignable to parameter type 'System.Predicate'
public void ManiPulateCategory(string categoryToManipulate)
{
createCategories = repository.Load(path);
foreach (Category item in createCategories)
{
createCategories.Remove(item.CategoryName)
}
}
I think that you are trying to remove from your list of categories ALL items that have a CategoryName which matches categoryToManipulate.
If that's what you want, you can do it using List.RemoveAll() like so:
createCategories.RemoveAll
(
catagory => catagory.CategoryName == categoryToManipulate
);
This is using a method on List, NOT something from IEnumerable. If you only have an IEnumerable available, you would have to use a different solution - but you said you have a List, so this should work.
This works by you passing what's known as a predicate to RemoveAll(). A predicate is simply a method takes a single parameter of a certain type and that returns true or false. It will be called once for each element of the list, being passed that element as a parameter. If it returns true, that element will be removed.
In this case, I didn't create a separate method for the predicate; instead I wrote an inline lambda expression to implement it.
createCategories.RemoveAll(x=>x.CategoryName == categoryToManipulate)
Something like that? (Fixed to reflect comments but initially proposed by Matthew Watson above)
Also have a look at this Answer
In order to find the right item in a list you have to override Equals and GetHashCode from Object.
class Category {
public override bool Equals(object obj)
{
if (!(obj is Category)) return false;
return this.CategoryName == ((Category)obj).CategoryName;
}
public override int GetHashCode()
{
this.CategoryName.GetHashCodeU();
}
}
Now you may call createCategories.remove(item) within your loop.
Related
I'm trying to create a method with generic parameters:
public List<DTListItem> MapDTListResponse(List<App.Order.DT> dtList)
{
return dtList.Select(MapDTListResponse).ToList();
}
public DTListItem MapDTListResponse(App.Order.DT dt)
{
return RecMap<DTListItem, App.Order.DT>(dt);
}
private T RecMap<T,TU>(TU newObject)
{
if (TU is IEnumerable) // this doesn't work; what do i check for here
{
//Also, how do i get this bit to replicate MapDTListReponse
newObject.Select(RecMap).ToList();
}
else
{
return Mapper.Map<T>(newObject);
}
}
As you can see, the first method takes and returns a collection and simply calls the second method (having the same name but different signature) for each element in the collection.
I want to create a generic method which will handle both cases. It should call itself if a collection is passed through. For this I need to check if the type is IEnumerable but the line T is IEnumerable has the following error
TU is a type which is not valid in the given context.
Also, newObject.Select(Map).ToList(); has the following error
TU does not contain a definition for Select
The is operator takes an object instance on its left hand side, so it can't be used like that. Instead, you can do this:
if (newObject is IEnumerable) // ...
And because you want to use the instance as a collection later on, you can use the as operator instead:
var newCollection = newObject as IEnumerable<T>;
if (newCollection != null) // ...
Worth pointing out that in cases where all you have is a type (and not an instance), you can achieve the same thing through the IsAssignableFrom method of the Type class, like this:
public static bool IsSequence<T>() => typeof(IEnumerable).IsAssignableFrom(typeof(T));
I have a generic method and it's possible that the object passed is a single object or a list of objects. Example:
public void MyGenericMethod<T>(T something, int? index)
{
// if it is a list how do I get to the object in the list?
}
There are cases when someone will pass a List. If they do pass a list of objects I will then use the index parameter to get the single object out of the list. I can assume that if index is not null then they passed in a list, but then how do I get to that value? I can't do this:
object temp = something[index.Value];
It's important to note that I cannot force the user to pass in a single object into my generic method. Also I cannot make it an array (T[]) and force the user to pass in an array (or a List).
You can use a cast to get the IList.
IList list = something as IList;
if( list != null )
{
object temp = list[index.Value];
}
However it might be simpler and more type safe to have a generic method overload dedicated to IList instead of one massive generic method.
public void MyGenericMethod<T>(IList<T> something, int index)
{
var item = something[index];
// etc...
}
Your requirements seem a bit wierd... why not do the following:
public void MyGenericMethod<T>(T something)
{
// let the user pass in the correct item
}
And simply let the user handle it, after all how is:
MyGenericMethod(MyList, 1);
Significantly better than:
MyGenericMethod(MyList[1])
???
Though if you really want I'd write it like so:
public void MyGenericMethod<T>(T something) //Base Method
{
// let the user pass in the correct item
}
public void MyGenericMethod<IList<T>>(IList<T> list, int index) //Overload
{
MyGenericMethod(list[index]);
}
Generics are meant to be used if your code does not care about the concrete type. If you still want to do this you need to cast:
IList list = (IList)something;
Or, if it is a generic list you need to do reflection access to invoke the list indexer at runtime if the element type is not statically known to you.
This (inefficient) snippet might also help you:
List<object> list = ((IEnumerable)something).Cast<object>().ToList();
Those are some ugly tricks. There is no clean way because, again, you are slightly misusing the feature.
Also, you don't need generics at all. Just type the parameter as object.
Like usr said, Generics aren't really supposed to be used in this way.
You could do a check to see if it's a list and if so iterate over it like this:
IList<T> enumerable = something as IList<T>;
if (enumerable != null)
{
foreach (T item in enumerable)
{
// Do something
}
}
If your T can be anything (which I don't recommend, since it breaks the SOLID principle) and what to handle it as a list you can do:
public void MyGenericMethod<T>(T something, int? index)
{
IList list = something as IList;
if (list != null)
{
//Do Something
}
else
{
//Do something else
}
}
Or you can do one of the following:
public void MyGenericMethod<T>(T something, int? index) where T : IList
{
IList list = (IList)something; //This will always work ok
//Do Something
}
I recommend the following, if feasible
public void MyGenericMethod(IList something, int? index)
{
//Do Something
}
I have a list which contains objects but these objests aren't unique in the list. I wrte this code to make unique them in another list:
foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => !resultSet.Contains(categoryProductsResult)))
{
resultSet.Add(categoryProductsResult);
}
But at the end resultSet is the same with categoryProductsResults.
categoryProductsResult's second row :
resultSet first row:
As you can see resultSet's first row and categoryProductsResult's second row is the same but it adds the second row to resultSet.
Do you have any suggestion?
Contains uses the default comparer which is comparing references since your class does not override Equals and GetHashCode.
class CategoryProductsResult
{
public string Name { get; set; }
// ...
public override bool Equals(object obj)
{
if(obj == null)return false;
CategoryProductsResult other = obj as CategoryProductsResult;
if(other == null)return false;
return other.Name == this.Name;
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
}
Now you can simply use:
resultSet = categoryProductsResults.Distinct().ToList();
List uses the comparer returned by EqualityComparer.Default and according to the documentation for that:
The Default property checks whether type T implements the
System.IEquatable(Of T) interface and, if so, returns an
EqualityComparer(Of T) that uses that implementation. Otherwise, it
returns an EqualityComparer(Of T) that uses the overrides of
Object.Equals and Object.GetHashCode provided by T.
So you can either implement IEquatable on your custom class, or override the Equals (and GetHashCode) methods to do the comparison by the properties you require. Alternatively you could use linq:
bool contains = list.Any(i => i.Id == obj.Id);
Each categoryProductsResult is different to each other. It's like something your can see here. If you want a simpler one and the ProductId is your unique identifier. Just do the code below:
foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => resultSet.ProductId !=categoryProductsResult.ProductId)
{
resultSet.Add(categoryProductsResult);
}
Reference objects in a list are indexed by their hash code. So, Contains will never find a reference object with the same hash code (unless you override the GetHashCode and Equals implementation in the class.
This SO answer explains.
You need to check if your current item is contained in your target list for each iteration. Currently you check once at the start of the loop, which means none of your items is in the target list.
I think Distinct is already doing what you want, you might want to use this extension instead of your own loop.
This issue has been bugging me for a while. Abstractly speaking, regardless of language, there are often situations when you want to have a method like this:
Collection method(Collection c) {
// select some elements from c based on some filter
// and return a new collection
}
Now, Collection is in this case some abstract class (Like say IList in C# or List in Java) with several implementations. I've been wondering what exactly is the right procedure to produce the abstract collection?
Is it ok to create a concrete collection inside the method and return it? Like:
Collection method(Collection c) {
Collection cc = new ConcreteCollection();
// select some elements from c based on some filter
return cc;
}
This of course puts a constraint on the resulting collection and will produce problems in case, for some reason, we want to cast the result of the method to a different concrete collection than the one used inside the method.
Or, use reflection to determine the actual concrete type of c and create an instance of that class:
Collection method(Collection c) {
Collection cc = c.getClass().newInstance();
// select some elements from c based on some filter
return cc;
}
For some reason this does not seem very "elegant" to me. I would greatly appreciate some insight in this matter.
(Speaking for java). The reason you're returning Collection (an interface) rather than a concrete type (such as ArrayList) is that you're telling the user that they shouldn't care about what the actual concrete type being used is. This leaves you free to choose the appropriate type for your library/api.
If you're enforcing a particular concrete class, then you should be returning that concrete class, rather than the interface.
So, they shouldn't be casting your return type to anything else other than Collection. See
When should I return the Interface and when the concrete class?.
In Java, there are actually some good examples of how to do this in the java.util.Collections class. Instead of taking a Collection and returning a Collection, the key methods take two collections, the "src" and the "dest". For example, Look at the signature of the copy method:
public static <T> void copy(List<? super T> dest, List<? extends T> src)
This puts the responsibility of instantiating the destination list on the caller.
I think you could do the same thing when you want to create a method that acts on a src Collection and puts the results into a destination Collection (rather than Lists).
I agree with Matthew Farwell's answer that you probably just want to return the interface and utilize that, but for the times when you really do need to work with a specific implementing class you can do it the same way the Collections class does it.
One approach you could take is to create a Collection implementation that delegates calls through to the original Collection. This defers the potentially expensive operation of filtering a large Collection until you need to explicitly read elements. It also saves memory.
Example
public interface Filter<T> {
boolean include(T t);
}
public class FilterCollection<T> implements Collection<T> {
private final Collection<T> orig;
private final Filter<T> filter;
public FilterCollection(Collection<T> orig, Filter<T> filter) {
this.orig = orig;
this.filter = filter;
}
public int size() {
int sz = 0;
for (T t : orig) {
if (filter.include(t)) {
++sz;
}
}
return sz;
}
public boolean contains(Object o) {
return o instanceof T && filter.include((T) o) && orig.contains(o);
}
public boolean add(T t) {
if (!filter.include(t)) {
throw new IllegalArgumentException("Element lies outside filter bounds.");
}
orig.add(t);
}
}
The caller should assume a given type of Collection is returned.
Instead it should either copy to the desired type or pass the desired type.
e.g.
Set<T> set2 = new HashSet<T>(filter(set));
List<T> list2 = new ArrayList<T>(filter(list));
or
filter(set2, set); // the target collection is passed.
filter(list2, list);
To the question about ConcreteCollection, it is definitely allowable.
To the concern about having a different concrete collection expected, there are a few ways to go around the problem:
Change the return type of the method. Example:
ConcreteCollection method(Collection c){
ConcreteCollection cc=new ConcreteCollection
for(Object x: c){
//do something
}
return cc
}
Make use of polymorphism. Example:
Collection x=method(c)
x.add(new Object) //add is a method defined within the abstract Collection
Use some utilities to cast the type. Example:
LinkedList h=Collections.toLinkedList(method(c))
Hoped my answer helped. ^^
As far as I can understand, you want to know how to make a method that accepts generic list and returns another modified generic list.
So, my advice will be to use an abstract type that implements method to modify its state.
IList<object> list = new List<object>();
list.Add(new object());
list.Remove(obj);
Or as showed above, instantiate a list that implements IList (or the Java equivalent) work with this instance and return the result as a IList
Edit
If you want to filter some item from a list to a new one, generics can help (I don't know if this feature exists in Java).
public IList<T> Filter<T>(IList<T> list)
{
var result = new List<T>();
result.Add(list[0]); // Or whatever filtering method
return result;
}
If you want your method to accept as many different collection types as possible, and you want to be sure that the result is the same implementation type as what you put in, you might want to use a void method which directly modifies the supplied collection. For instance:
import com.google.common.base.Predicate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class Testy {
private static <T> void filter(Iterable<T> collection, Predicate<T> filter) {
Iterator<T> iterator = collection.iterator();
while (iterator.hasNext()) {
if (!filter.apply(iterator.next())) { // Condition goes here
iterator.remove();
}
}
}
public static void main(String... args) {
List<String> list = new ArrayList<String>();
list.addAll(Arrays.asList("A", "B", "C", "D"));
filter(list, new Predicate<String>() { // Anonymous filter (predicate)
#Override public boolean apply(String input) {
return input.equals("B");
}
});
System.out.println(list); // Prints ["B"]
}
}
The helper method filter takes an Iterable, the simplest type required for iterating over something. Apply the filter to each element, and if the predicate (filter) returns false, remove that element from the underlying collection with Iterator.remove().
The Predicate<T> interface here comes from Google. You can easily write your own if you don't wish to import it. The only required method is apply(T) which returns a boolean. Either that, or just write your condition directly inside the loop and get rid of the second parameter.
This method is the most efficient if your original collection is mutable and you don't wish to keep any intermediate results.
Another option is to use Google Collections Collections2.filter(Collection<E>, Predicate<E>) which returns a Collection<E> just like in your question. Similarly, the Iterables class will do the same thing, but create lazy iterables where the filters are only applied when actually doing the iterating.
Here is the story:
Im trying to make a list of different clusters... I only want to have the necessary clusters... And Clusters can be the same.
How can I add this to a list by checking if the list contains the object (I know objects cant be passed here)
This is my sample quote:
foreach (Cluster cluster in clustersByProgramme)
{
if (!clusterList.Contains(cluster))
{
clusterList.Add(cluster);
}
}
Your code should work; if it hasn't, you might be using different object instances that represent the same actual cluster, and you perhaps haven't provided a suitable Equals implementation (you should also update GetHashCode at the same time).
Also - in .NET 3.5, this could be simply:
var clusterList = clustersByProgramme.Distinct().ToList();
As an example of class that supports equality tests:
class Cluster // possibly also IEquatable<Cluster>
{
public string Name { get { return name; } }
private readonly string name;
public Cluster(string name) { this.name = name ?? ""; }
public override string ToString() { return Name; }
public override int GetHashCode() { return Name.GetHashCode(); }
public override bool Equals(object obj)
{
Cluster other = obj as Cluster;
return obj == null ? false : this.Name == other.Name;
}
}
Your example is about as simple as it is going to get. The only thing I could possibly recommend is that you use the Exists method:
The Predicate is a delegate to a
method that returns true if the object
passed to it matches the conditions
defined in the delegate. The elements
of the current List are individually
passed to the Predicate delegate, and
processing is stopped when a match is
found.
This method performs a linear search;
therefore, this method is an O(n)
operation, where n is Count.
If you're using .NET 3.5, use a HashSet to do this.
HashSet<Cluster> clusterList = new HashSet<Cluster>();
foreach (Cluster cluster in clustersByProgramme)
{
clusterList.Add(cluster);
}
In this case, also make sure that if cluster1 == cluster2, then
cluster1.Equals(cluster2);
cluster2.Equals(cluster1); //yeah, could be different depending on your impl
cluster1.GetHashCode() == cluster2.GetHashCode();
Your code is correct, but it is not very efficient. You could instead use a HashSet<T> like this:
HashSet<Cluster> clusterSet = new HashSet<T>();
foreach (Cluster cluster in clustersByProgramme)
clusterSet.Add(cluster);
In this case, also make sure that if cluster1 == cluster2, then
cluster1.Equals(cluster2);
cluster2.Equals(cluster1); //yeah, could be different depending on your impl
cluster1.GetHashCode() == cluster2.GetHashCode();
why not just use dictionary?
It is n(1) as long as your items have a good hash.
Seems a simple solution
Ie dictionary.Contains(key) is n(1)
you can then update existing if at all or add new