In my app I have a scenario in which I get a list of unknown type that could be either int\long\short.
I need to convert this list to double.
what is the quickest and most efficient way to achieve this? (it needs to be as fast as it could be)
I assume you have List<object> and you need to convert it to List<double>
Try this, this will work for all types which implements IConvertible. long, int, short, float,etc...
var doubleList = objectList.Select(x=> Convert.ToDouble(x)).ToList();
try this
List<double> doubleList = intList.ConvertAll(x => (double)x);
Nicely simple:
var doubleList = listOfObjects.Select(i => Convert.ToDouble(i)).ToList();
Micro-optimising because you say "most efficient" is important:
int count = listOfObjects.Count;
var doubleList = new List<double>(listOfObjects.Count);
for(int i = 0; i != count; ++i)
doubleList.Add(Convert.ToDouble(listOfObjects[i]));
However, "most efficient" depends on just what you need it to be most efficient at. You get different efficiencies with:
public class DoubleList : IList<double>
{
private readonly List<object> _source; // Change to IList<object> if that's a possibility
public DoubleList(List<object> source)
{
_source = _source;
}
// Hide half-supported implementation from main interface
double IList<double>.this[int index]
{
get { return Convert.ToDouble(_source[index]); }
set { throw new NotSupportedException("Read-only collection"); }
}
public double this[int index]
{
get { return Convert.ToDouble(_source[index]); }
}
public int Count
{
get { return _source.Count; }
}
bool ICollection<double>.IsReadOnly
{
get { return true; }
}
/* Lots of boring and obvious implementations skipped */
public struct Enumerator : IEnumerator<double>
{
// note, normally we'd just use yield return in the
// GetEnumerator(), and we certainly wouldn't use
// a struct here (there are issues), but this
// optimisation is in the spirit of "most efficient"
private List<object>.Enumerator _en; //Mutable struct! Don't make field readonly!
public double Current
{
get { return Convert.ToDouble(_en.Current); }
}
object IEnumerator.Current
{
get { return Current; }
}
public void Dispose()
{
_en.Dispose();
}
public bool MoveNext()
{
return _en.MoveNext();
}
public void Reset()
{
_en.Reset();
}
}
public Enumerator GetEnumerator()
{
return new Enumerator(_source.GetEnumerator());
}
IEnumerator<double> IEnumerable<double>.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
var doubleList = new DoubleList(listOfObjects);
This moves around what happens when in such a way as to change what costs what. You'll return in constant time, but actually using the list will be more expensive. However, if you're only going to look at a few fields, or perhaps only going to obtain the count and then enumerate through it, then the fact that this doesn't do a full copy can make it much more efficient.
Related
Java has Collections.singletonList(T) which returns a List<T> of exactly one element. Is there something similar in C# that returns an IList?
IEnumerable<T> enumerable = Enumerable.Repeat(t, 1);
Creates an IEnumerable with one element.
Array implements IList; and the length cannot be modified via Add (as ReadOnly is true).
Thus, SingletonList<int> could be implemented as easily as:
var slist = new int[] { 5 };
You may want to wrap it in a System.Collections.ObjectModel.ReadOnlyCollection<T> so that the single value cannot be changed (if the Java Singleton list works like this). E.g.
var slist = new System.Collections.ObjectModel.ReadOnlyCollection<int>(new int[] { 5 });
You can also create an extension method.
public static IList<T> AsSingletonList<T>(this IEnumerable<T> source)
{
foreach (var item in source)
{
return new System.Collections.ObjectModel.ReadOnlyCollection<T>(new T[] { item });
}
return new System.Collections.ObjectModel.ReadOnlyCollection<T>(new T[] { default(T) });
}
Or one that asserts there is exactly one value in the source:
public static IList<T> AsSingletonList<T>(this IEnumerable<T> source)
{
IList<T> result = null;
foreach (var item in source)
{
if (result != null)
throw new ArgumentOutOfRangeException("source", "Source had more than one value.");
result = new System.Collections.ObjectModel.ReadOnlyCollection<T>(new T[] { item });
}
if (result == null)
throw new ArgumentOutOfRangeException("source", "Source had no values.");
return result;
}
Edit: Used ReadOnlyCollection<T> to prevent mutation of the single value.
Note: While I think the other answers are correct, the List<T> by default has a capacity of 10 - which is a tiny bit wasteful.
To answer your question, no. Sadly there is nothing built in, although it would often be useful when working with IEnumerable. You'll have to roll your own.
Update
Instead of using workarounds, here's an example of an efficient and immutable SingletonList that implements IList<T>:
Usage
SingletonList<int> bling = new SingletonList<int>(10);
Code
public class SingletonList<T> : IList<T>
{
private readonly T _item;
public SingletonList(T item)
{
_item = item;
}
public IEnumerator<T> GetEnumerator()
{
yield return _item;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
throw new NotSupportedException("Add not supported.");
}
public void Clear()
{
throw new NotSupportedException("Clear not supported.");
}
public bool Contains(T item)
{
if (item == null) return _item == null;
return item.Equals(_item);
}
public void CopyTo(T[] array, int arrayIndex)
{
if (array == null) throw new ArgumentNullException("array");
array[arrayIndex] = _item;
}
public bool Remove(T item)
{
throw new NotSupportedException("Remove not supported.");
}
public int Count
{
get { return 1; }
}
public bool IsReadOnly
{
get { return true; }
}
public int IndexOf(T item)
{
return Contains(item) ? 0 : -1;
}
public void Insert(int index, T item)
{
throw new NotSupportedException("Insert not supported.");
}
public void RemoveAt(int index)
{
throw new NotSupportedException("RemoveAt not supported.");
}
public T this[int index]
{
get
{
if (index == 0) return _item;
throw new IndexOutOfRangeException();
}
set { throw new NotSupportedException("Set not supported."); }
}
}
public static class IListExtensions
{
public static IList<T> SingletonList<T>(this IList<T> iList, T item)
{
return Enumerable.Range(0, 1).Select(i => item).ToList().AsReadOnly();
// or
var Result = new List<T>();
Result.Add(item);
return Result.AsReadOnly();
}
}
In C#, you can use a list initializer with one element:
var x = new List<int> { 3 };
Contrary to singletonList, this list is mutable. If you want something immutable, you can call AsReadOnly() on the resulting object:
// Looks strange, but, yes, this is actually valid C#.
var x = new List<int> { 3 }.AsReadOnly();
This is a first for me: I am submitting an answer ... what I have to say does not lead itself to a comment, imho ... to a question which I think I do not fully understand ... in order to better understand the question. Consider:
public class singletonList<T> : List<T>
{
public singletonList(T theValue) { base.Add(theValue); }
public new void Add(T anotherValue) {}
public new void AddRange(T anotherValue) {}
public new void Clear() {}
public new void Insert(int index, T anotherValue) {}
public new void ToArray() {}
}
This will create a new List of whatever Type which allows only one instance of its value-Type to exist inside the List. Obviously it's not fully 'fleshed-out' since you could still use 'InsertRange' and other List altering commands.
Here's a test verifying its 'immutable' for the internal List operators masked-out by the use of 'new' in their declarations.
var q = new singletonList<int>(99);
q.Add(100);
q.Clear();
q.Insert(0, 788);
I doubt this is what the OP wants, but I am curious if this perhaps does, meet the OP's spec in any way.
In spite of ChibaCity's kind explanations, I am still utterly baffled why one would ever want to use a List that contained only one element.
Thanks in advance for educating me, and if the cost of enlightenment is loss of votes, or face ... no problem; at my age I am not running for anything except staying in place, and face is best forgotten :)
I passed a new[] { alreadyDeclaredVariable } into the function. That's one way to do it, just making an in-place array of 1 element.
Why in this example from MSDN, in GetEnumerator method, PeopleEnum returns IEnumerator?
public class Person
{
public Person(string fName, string lName)
{
this.firstName = fName;
this.lastName = lName;
}
public string firstName;
public string lastName;
}
public class People : IEnumerable
{
private Person[] _people;
public People(Person[] pArray)
{
_people = new Person[pArray.Length];
for (int i = 0; i < pArray.Length; i++)
{
_people[i] = pArray[i];
}
}
//why???
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator) GetEnumerator();
}
public PeopleEnum GetEnumerator()
{
return new PeopleEnum(_people);
}
}
public class PeopleEnum : IEnumerator
{
public Person[] _people;
// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;
public PeopleEnum(Person[] list)
{
_people = list;
}
public bool MoveNext()
{
position++;
return (position < _people.Length);
}
public void Reset()
{
position = -1;
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public Person Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
UPDATE:
BTW, if Array data type implements ICloneable interface, why msdn has copied pArray to _people by writing a for loop?
It needs to return exactly IEnumerator to properly implement the IEnumerable interface. It is doing this using an "explicit interface implementation", so on the public API you see PeopleEnum, but IEnumerable is still happy
But in reality you would very rarely write an enumerator this way in C# 2.0 or above; you'd use an iterator block (yield return). See C# in Depth chapter 6 (free chapter!).
For info, the reason that PeopleEnum exists at all here is that this looks like a .NET 1.1 sample, where that is the only way to create a typed enumerator. In .NET 2.0 and above there is IEnumerable<T> / IEnumerator<T>, which has a typed (via generics) .Current.
In .NET 2.0 / C# 2.0 (or above) I would have simply:
public class People : IEnumerable<Person> {
/* snip */
public IEnumerator<Person> GetEnumerator() {
return ((IEnumerable<Person>)_people).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() { return _people.GetEnumerator();}
}
Types implementing IEnumerable require a method called GetEnumerator that returns an IEnumerator. In that example (which is pretty obsolete as of C# 2.0) there is an enumerator class PeopleEnum that implements IEnumerator. It's what's used internally by the C# foreach statement.
A more up to date example would look more like the following. Note there's no longer a need for a PeopleEnum class now that C# supports iterators. Effectively the compiler does all the heavy lifting for you.
public class People : IEnumerable
{
private Person[] _people;
public People(Person[] pArray)
{
_people = new Person[pArray.Length];
for (int i = 0; i < pArray.Length; i++)
{
_people[i] = pArray[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
for (int i=0; i < _people.Length; i++) {
yield return _people[i];
}
}
}
I'm not entirely sure if I have all the terminology correct so forgive me if I'm wrong. I was wondering if it would be possible to send an argument(s) to the method. Take the following for example.
public item (int index)
{
get { return list[index]; }
set { list[index] = value; }
}
I know that as it is, it will error. What I'm asking is if there is some way to get it working. Any suggestions or should I figure out some way around it?
Thanks in advance.
Try this:
// This returns an instance of type "Foo",
// since I didn't know the type of "list".
// Obviously the return type would need to
// match the type of whatever "list" contains.
public Foo this[int index]
{
get { return list[index]; }
set { list[index] = value; }
}
This is C#'s indexer syntax and it has some limitations (it's not as flexible as VB.NET's parameterful properties) but it does work for your specific example.
As others have shown, you can turn it into an indexer - which can have multiple parameters, by the way.
What you can't do is name an indexer in C#... although you can in VB. So you can't have two indexers, one called Foo and the other called Bar... you'd need to write properties which returned values which were themselves indexable. It's a bit of a pain, to be honest :(
This is called indexer property
public int this [int index]
{
get { return list[index]; }
set { list[index] = value; }
}
I think what you might be looking for is:
public Something this[int index]
{
get
{
return list[index];
}
set
{
list[index] = value;
}
}
For the record, Whilst the other answers are valid, you might also want to consider using the following approach:
public IList<Something> items { get; set; }
This could then be used as follows:
Something item = myFoo.items[1];
The other answers would be used in the following, slightly different, way:
Something item = myFoo[1];
The one you want depends on what exactly you are trying to achieve, which is difficult to determine without seeing the rest of the code.
Besides the indexer that has been mentioned several times now, another possibility is to make a custom class with an indexer and return an instance of it as a property.
Example:
public class IntList
{
public IntList(IEnumerable<int> source)
{
items = source.ToArray();
Squares = new SquareList(this);
}
private int[] items;
// The indexer everyone else mentioned
public int this[int index]
{
get { return items[index]; }
set { items[index] = value; }
}
// Other properties might be useful:
public SquareList Squares { get; private set; }
public class SquareList
{
public SquareList(IntList list)
{
this.list = list;
}
private IntList list;
public int this[int index]
{
get { return list.items[index] * list.items[index]; }
}
}
}
You can use indexator for solving this problem
public object this[string name]
{
get
{
int idx = FindParam(name);
if (idx != -1)
return _params[idx].Value;
throw new IndexOutOfRangeException(String.Format("Parameter \"{0}\" not found in this collection", name));
}
set
{
int idx = FindParam(name);
if (idx != -1)
_params[idx].Value = value;
else
throw new IndexOutOfRangeException(String.Format("Parameter \"{0}\" not found in this collection", name));
}
}
I have a DataSource in my control which is always a List<T> where T has to inherit from IEntity.
public class MyClass<T> where T : IEntity
{
public List<T> DataSource
{
get;
set;
}
}
Now, obviously you can't cast a List<T> to a List<IEntity> doing the following:
List<IEntity> wontWork = (List<IEntity>)this.DataSource;
How can I get the DataSource as a List of IEntity, whilst still being able to add and remove items from the DataSource? I.e. I could do the following, but removing from the List it returns would not remove from the DataSource:
public List<TOut> GetDataSourceCopyAsUnderlyingType<TOut>()
{
if (this.DataSource == null)
{
return new List<TOut>();
}
else
{
// Get the list and the enumerator
IList list = (IList)this.DataSource;
IEnumerator enumerator = list.GetEnumerator();
// Build the target list
List<TOut> targetList = new List<TOut>();
int i = 0;
while (enumerator.MoveNext())
{
TOut entity = (TOut)list[i];
targetList.Add(entity);
i++;
}
return targetList;
}
}
Basically, I need some way of doing the following:
List<IEntity> interfaceList = this.GetDataSourceAsAnotherType<IEntity>();
int dataSourceCount = this.DataSource.Count; // Equals 5
int interfaceCount = interfaceList.Count; // Equals 5
interfaceList.RemoveAt(0);
int dataSourceCount = this.DataSource.Count; // Equals 4
int interfaceCount = interfaceList.Count; // Equals 4
And just to add, I don't mind if it means I've got to use a different type instead of a List.
EDIT: Sorry, forgot to say I'm using .Net2.0 and cannot move to .Net 3.5.
It would be a monumentally bad idea if this were allowed, which is why it isn't. I can add any old IEntity to a List<IEntity> which will blow up if that IEntity can't be cast to T. Whilst all Ts are IEntities, not all IEntities are Ts.
This works with arrays because arrays have a deliberate subtyping hole (as they do in Java). Collections do not have a subtyping hole.
Create a wrapper class that seamlessly converts. Untested sample:
public class CastList<TTarget, TOriginal>
: IList<TTarget> where TOriginal : TTarget
{
List<TOriginal> _orig;
public CastList(List<TOriginal> orig) { _orig = orig; }
public Add(TTarget item) { _orig.Add(item); }
public TTarget this[int i]
{
get { return (TTarget)_orig[i]; }
set { _orig[i] = value; }
}
public IEnumerator<TTarget> GetEnumerator()
{
foreach(TOriginal item in _orig)
yield return (TTarget)item;
}
// etc...
}
Manipulations of the original list will also be reflected in the wrapper. To use this, just construct it with your DataSource.
What DrPizza said, but with more code:
public class ListFacade<TIn, TOut> : IList<TOut> where TIn : TOut
{
private readonly IList<TIn> innerList;
public ListFacade(IList<TIn> innerList)
{
this.innerList = innerList;
}
public int Count
{
get { return this.innerList.Count; }
}
public bool IsReadOnly
{
get { return this.innerList.IsReadOnly; }
}
public TOut this[int index]
{
get { return this.innerList[index]; }
set { this.innerList[index] = (TIn)value; }
}
public void Add(TOut item)
{
this.innerList.Add((TIn)item);
}
public void Clear()
{
this.innerList.Clear();
}
public bool Contains(TOut item)
{
return (item is TIn) && this.innerList.Contains((TIn)item);
}
public void CopyTo(TOut[] array, int arrayIndex)
{
var inArray = new TIn[this.innerList.Count];
this.innerList.CopyTo(inArray, arrayIndex);
Array.Copy(inArray, array, inArray.Length);
}
public IEnumerator<TOut> GetEnumerator()
{
foreach (var item in this.innerList)
{
yield return item;
}
}
System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public int IndexOf(TOut item)
{
return (item is TIn) ? this.innerList.IndexOf((TIn)item) : -1;
}
public void Insert(int index, TOut item)
{
this.innerList.Insert(index, (TIn)item);
}
public bool Remove(TOut item)
{
return (item is TIn) && this.innerList.Remove((TIn)item);
}
public void RemoveAt(int index)
{
this.innerList.RemoveAt(index);
}
Add, Insert and the indexer set will blow up if the argument is not of type TIn.
ok this might be completely beside the point but, how about using a little bit of Linq?
var interfaceList = objectList.ConvertAll<Interface>(o => (Interface)o);
this way you can cast the objectList easily.
hope this helps to find the solution...
I'm in favor of linq too, but you can do it like:
var interfaceList = objectList.Cast<IEntity>();
Which is shorter and more expressive.
I need to sort some objects according to their contents (in fact according to one of their properties, which is NOT the key and may be duplicated between different objects).
.NET provides two classes (SortedDictionary and SortedList), and both are implemented using a binary tree. The only differences between them are
SortedList uses less memory than SortedDictionary.
SortedDictionary has faster insertion and removal operations for unsorted data, O(log n) as opposed to O(n) for SortedList.
If the list is populated all at once from sorted data, SortedList is faster than SortedDictionary.
I could achieve what I want using a List, and then using its Sort() method with a custom implementation of IComparer, but it would not be time-efficient as I would sort the whole List each time I want to insert a new object, whereas a good SortedList would just insert the item at the right position.
What I need is a SortedList class with a RefreshPosition(int index) to move only the changed (or inserted) object rather than resorting the whole list each time an object inside changes.
Am I missing something obvious ?
Maybe I'm slow, but isn't this the easiest implementation ever?
class SortedList<T> : List<T>
{
public new void Add(T item)
{
Insert(~BinarySearch(item), item);
}
}
http://msdn.microsoft.com/en-us/library/w4e7fxsh.aspx
Unfortunately, Add wasn't overrideable so I had to new it which isn't so nice when you have List<T> list = new SortedList<T>; which I actually needed to do.... so I went ahead and rebuilt the whole thing...
class SortedList<T> : IList<T>
{
private List<T> list = new List<T>();
public int IndexOf(T item)
{
var index = list.BinarySearch(item);
return index < 0 ? -1 : index;
}
public void Insert(int index, T item)
{
throw new NotImplementedException("Cannot insert at index; must preserve order.");
}
public void RemoveAt(int index)
{
list.RemoveAt(index);
}
public T this[int index]
{
get
{
return list[index];
}
set
{
list.RemoveAt(index);
this.Add(value);
}
}
public void Add(T item)
{
list.Insert(~list.BinarySearch(item), item);
}
public void Clear()
{
list.Clear();
}
public bool Contains(T item)
{
return list.BinarySearch(item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex)
{
list.CopyTo(array, arrayIndex);
}
public int Count
{
get { return list.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
var index = list.BinarySearch(item);
if (index < 0) return false;
list.RemoveAt(index);
return true;
}
public IEnumerator<T> GetEnumerator()
{
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return list.GetEnumerator();
}
}
Or perhaps something like this is a more appropriate Remove function...
public bool Remove(T item)
{
var index = list.BinarySearch(item);
if (index < 0) return false;
while (((IComparable)item).CompareTo((IComparable)list[index]) == 0)
{
if (item == list[index])
{
list.RemoveAt(index);
return true;
}
index++;
}
return false;
}
Assuming items can compare equal but not be equal...
I eventually decided to write it :
class RealSortedList<T> : List<T>
{
public IComparer<T> comparer;
public int SortItem(int index)
{
T item = this[index];
this.RemoveAt(index);
int goodposition=FindLocation(this[index], 0, this.Count);
this.Insert(goodposition, item);
return goodposition;
}
public int FindLocation(T item, int begin, int end)
{
if (begin==end)
return begin;
int middle = begin + end / 2;
int comparisonvalue = comparer.Compare(item, this[middle]);
if (comparisonvalue < 0)
return FindLocation(item,begin, middle);
else if (comparisonvalue > 0)
return FindLocation(item,middle, end);
else
return middle;
}
}
Don't forget that inserting an item into a list backed by an array can be an expensive operation - inserting a bunch of items and then sorting may well be quicker unless you really need to sort after every single operation.
Alternatively, you could always wrap a list and make your add operation find the right place and insert it there.
I've solved this problem in the past by writing an extension method that does a binary search on a IList, and another that does an insert. You can look up the correct implementation in the CLR source because there's a built-in version that works only on arrays, and then just tweak it to be an extension on IList.
One of those "should be in the BCL already" things.
What I need is a SortedList class with
a RefreshPosition(int index) to move
only the changed (or inserted) object
rather than resorting the whole list
each time an object inside changes.
Why would you update using an index when such updates invalidate the index? Really, I would think that updating by object reference would be more convenient. You can do this with the SortedList - just remember that your Key type is the same as the return type of the function that extracts the comparable data form the object.
class UpdateableSortedList<K,V> {
private SortedList<K,V> list = new SortedList<K,V>();
public delegate K ExtractKeyFunc(V v);
private ExtractKeyFunc func;
public UpdateableSortedList(ExtractKeyFunc f) { func = f; }
public void Add(V v) {
list[func(v)] = v;
}
public void Update(V v) {
int i = list.IndexOfValue(v);
if (i >= 0) {
list.RemoveAt(i);
}
list[func(v)] = v;
}
public IEnumerable<T> Values { get { return list.Values; } }
}
Something like that I guess.