Basically, I have a collection of objects each implement a member of Type IValueCollection.
public interface IValueCollection : IEnumerable<decimal>
{
decimal this[int index] { get; set; }
}
MeasurementCollection.Values is of type IValueCollection.
With the logic below I want to pivot a collection of IValueCollection and wrote the extension method below.
public static IEnumerable<IValueCollection> PivotValues(this MeasurementCollection items)
{
if(items.IsQuantized())
{
int s = (int)items.First().Template.Frequency;
int c = items.Count;
for (int n = 0; n < s; n++)
{
IValueCollection v = new MeasurementValueCollection(c);
for (int m = 0; m < c; m++)
v[m] = items.ElementAt(m).Values[n];
yield return v;
}
}
}
should do
{{1,2,3}{4,5,6}{7,8,9}} results in {{1,4,7},{2,5,8},{3,6,9}}
However I think there is some nicer, slimmer and more readable expression to do this
can somebody point me in the right direction?
edit
info about underlying classes
interface IValueCollection : IEnumerable<decimal>
class MeasurementCollection : ICollection<IMeasurement>
interface IMeasurement
{
IMeasurementTemplate Template { get; }
......
}
interface IMeasurementTemplate
{
.....
MeasurementFrequency Frequency { get; }
}
I would, personally, force the evaluation of your collection in advance, and use it as an array. Right now, each time you call ElementAt, you're going to evaluate the IEnumerable<T> again, causing a lot of repeated searching.
By forcing it to evaluate to an array in advance, you simplify the entire process. Something like:
public static IEnumerable<IValueCollection> PivotValues(this MeasurementCollection items)
{
if(items.IsQuantized())
{
int elementLength = (int)items.First().Template.Frequency;
var itemArray = items.ToArray();
for (int n = 0; n < itemArray.Length; n++)
{
IValueCollection v = new MeasurementValueCollection(elementLength);
for (int m = 0; m < elementLength; m++)
{
v[m] = itemArray[m].Values[n];
}
yield return v;
}
}
else
yield break; // Handle the case where IsQuantized() returns false...
}
If you control MeasurementValueCollection, I would add a constructor which takes an IEnumerable<decimal> as input, as well. You could then do:
public static IEnumerable<IValueCollection> PivotValues(this MeasurementCollection items)
{
if(items.IsQuantized())
{
var elements = Enumerable.Range(0, (int)items.First().Template.Frequency);
var itemArray = items.ToArray();
foreach(var element in elements)
yield return new MeasurementValueCollection(
itemArray.Select(
(item,index) => itemArray[index].Value[element]
)
);
}
else
yield break; // Handle the case where IsQuantized() returns false...
}
Related
Is it possible to write a C# method that accepts a value tuple with any number of items of the same type and converts them into a list?
Edit 2/6/2019
I accepted the Provided answer as the correct one. I wanted to also provide a solution that uses a base class that is not an interface, becuase I am trying to write a conversion operator and user defined conversions from an interface are not allowed.
public static class TupleExtensions
{
public static IEnumerable<object> Enumerate(this ValueType tpl)
{
var ivt = tpl as ITuple;
if (ivt == null) yield break;
for (int i = 0; i < ivt.Length; i++)
{
yield return ivt[i];
}
}
}
You can use the fact that ValueTuples implement the ITuple interface.
The only issue is that tuple elements can be of arbitrary type, so the list must accept any kind of type.
public List<object> TupleToList(ITuple tuple)
{
var result = new List<object>(tuple.Length);
for (int i = 0; i < tuple.Length; i++)
{
result.Add(tuple[i]);
}
return result;
}
This also works as an extension method:
public static class ValueTupleExtensions
{
public static List<object> ToList(this ITuple tuple)
{
var result = new List<object>(tuple.Length);
for (int i = 0; i < tuple.Length; i++)
{
result.Add(tuple[i]);
}
return result;
}
}
This way it is possible to write var list = (123, "Text").ToList();.
Edit 2020-06-18: If every element of the tuple is of the same type it's possible to create list with the proper element type:
public List<T> TupleToList<T>(ITuple tuple)
{
var result = new List<T>(tuple.Length);
for (int i = 0; i < tuple.Length; i++)
{
result.Add((T)tuple[i]);
}
return result;
}
Lets say I have a list of items:
[a,b,b,a,c,d,a,d,b,c]
and I need to know, for each item, how many items along do I have to traverse till I get n unique items, (and return eg -1, or otherwise indicate if that's not possible)
So here, if n = 4, I would return
[6,5,4,6,5,5,4,-1,-1,-1]
since
a,b,b,a,c,d contains 4 unique elements
b,b,a,c,d contains 4 unique elements
b,a,c,d contains 4 unique elements,
a,c,d,a,d,b contains 4 unique elements
etc.
I used
List.Select((x,i) => {
var range = List.Skip(i).GroupBy(y => y).Take(n);
if (range.Count() == n)
return range.SelectMany(y => y).Count();
return -1;
});
Although i'm pretty sure this is horribly non-performant.
To try to minimize overhead, I created a ListSpan extension class for managing subparts of a List - something like ArraySegment for List, but (loosely) modeled on Span:
public class ListSpan<T> : IEnumerable<T>, IEnumerable {
List<T> baseList;
int start;
int len;
public ListSpan(List<T> src, int start = 0, int? len = null) {
baseList = src;
this.start = start;
this.len = len ?? (baseList.Count - start);
if (this.start + this.len > baseList.Count)
throw new ArgumentException("start+len > Count for ListSpan");
}
public T this[int n]
{
get
{
return baseList[start + n];
}
set
{
baseList[start + n] = value;
}
}
public class ListSpanEnumerator<Te> : IEnumerator<Te>, IEnumerator {
int pos;
List<Te> baseList;
int end;
Te cur = default(Te);
public ListSpanEnumerator(ListSpan<Te> src) {
pos = src.start - 1;
baseList = src.baseList;
end = src.start + src.len;
}
public Te Current => cur;
object IEnumerator.Current => Current;
public bool MoveNext() {
if (++pos < end) {
cur = baseList[pos];
return true;
}
else {
cur = default(Te);
return false;
}
}
public void Reset() => pos = 0;
public void Dispose() { }
}
public IEnumerator<T> GetEnumerator() => new ListSpanEnumerator<T>(this);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public static class ListExt {
public static ListSpan<T> Slice<T>(this List<T> src, int start = 0, int? len = null) => new ListSpan<T>(src, start, len);
}
Then I created an extension method to return the distance (in Take terms) required to get n unique items from an IEnumerable:
public static class IEnumerableExt {
public static int DistanceToUnique<T>(this IEnumerable<T> src, int n, IEqualityComparer<T> cmp = null) {
var hs = new HashSet<T>(cmp ?? EqualityComparer<T>.Default);
var pos = 0;
using (var e = src.GetEnumerator()) {
while (e.MoveNext()) {
++pos;
hs.Add(e.Current);
if (hs.Count == n)
return pos;
}
}
return -1;
}
}
Now the answer is relatively straight forward:
var ans = Enumerable.Range(0, src.Count).Select(p => src.Slice(p).DistanceToUnique(n));
Basically I go through each position in the original (src) List and compute the distance to n unique values from that position using a ListSpan of the List starting at that position.
This still isn't terribly efficient in that I am creating a HashSet for every element in the original List and putting all the following elements in it, and traversing the elements up to k! times for a k element List. Still trying to come up with something really efficient.
I was attempting to solve the running median problem (on hackerrank) using a sorted set. Only it's elements don't appear properly sorted.
See it in action here: http://rextester.com/NGBN25779
public class RunningMedian{
List<int> list = new List<int>();
SortedSet<int> sorted = new SortedSet<int>();
public void Add(int num){
list.Add(num);
sorted.Add(num);
}
public double MedianNotWorking(){
return GetMedian(sorted.ToArray());
}
public double MedianWorking(){
int[] arr = list.ToArray();
Array.Sort(arr);
return GetMedian(arr);
}
public double GetMedian(int[] arr){
int idx = list.Count / 2;
if(arr.Length % 2 == 0){
return (double)((double)(arr[idx] + arr[idx-1]) / 2);
}else{
return arr[idx];
}
}
}
static void Main(String[] args) {
int n = Convert.ToInt32(Console.ReadLine());
int[] a = new int[n];
RunningMedian heap = new RunningMedian();
for(int i = 0; i < n; i++){
a[i] = Convert.ToInt32(Console.ReadLine());
heap.Add(a[i]);
//double median = heap.GetMedian();
double median = heap.MedianNotWorking();
Console.WriteLine(median.ToString("F1"));
}
}
For the most part the sorted set does work. However at larger input sizes it begins to give wrong answers. It may not be the optimal solution to the problem but I'm curious as to why it fails at all. C# doesn't have a min-heap / priority queue so why can't sorted sets be used as a substitute?
*Edited to include full code from hackerrank.
Here is an input file.
Input
http://textuploader.com/dovni
Expected
http://textuploader.com/dovnb
Output
http://textuploader.com/dovwj
Conflicts appear near the end
Expected
(Skipping 1-364)
54240.0
54576.5
54913.0
54576.5
54240.0
Results
(Skipping 1-364)
54240.0
54576.5
54913.0
54963.0
54576.5
SortedSet collections contain by definition only unique values. However your input file contains the number 21794 twice, which means that the second 21794 entry doesn't get added to your SortedSet. So your sorted set will contain fewer values than your list and your whole algorithm doesn't work anymore.
In general, this could be achieved by definition of new IComparator behavior for the SortedSet comparison. For the min priority queue it would be smth like this:
public class PriorityQueue<K,V> where K : IComparable
where V : IComparable
{
private SortedSet<Node<K,V>> _set;
private readonly int _amount;
public PriorityQueue(int amount)
{
_set = new SortedSet<Node<K,V>>(new PriorityComparer<K,V>());
_amount = amount;
}
public void Add(Node<K,V> value)
{
if (_amount > _set.Count)
_set.Add(value);
else
{
if (_set.Max.Val.CompareTo(value.Val) == 1)
{
_set.Remove(_set.Max);
_set.Add(value);
}
}
}
public Node<K,V> ExtractMax()
{
var max = _set.Max;
_set.Remove(max);
return max;
}
public Node<K,V> ExtractMin()
{
var min = _set.Min;
_set.Remove(min);
return min;
}
public bool IsEmpty => _set.Count == 0;
}
public struct Node<K,V> where K : IComparable
where V : IComparable
{
public K Key;
public V Val;
public Node(K key, V val)
{
Val = val;
Key = key;
}
}
public class PriorityComparer<K,V> : IComparer<Node<K,V>> where K: IComparable
where V: IComparable
{
public int Compare(Node<K,V> i, Node<K,V> y)
{
var compareresult = i.Val.CompareTo(y.Val);
if (compareresult == 0)
return i.Key.CompareTo(y.Key);
return compareresult;
}
}
I recently designed a data structure similar to 'Queue' and 'Stack' for a special purpose, with a fixed maximum number of objects in it and when it is full and inserted, the first inserted object drops out.
The Code:
public class AssemblyLine<T>
{
private long length;
public long Length { get { return this.length; } }
private T[] data;
private long Pointer = 0;
private long count = 0;
public long Count { get { return this.count; } }
public void Insert(T obj)
{
this.Data[Pointer] = obj;
this.Next();
if (this.count < this.length)
this.count++;
}
public T[] GetLastX(long x)
{
long p = this.Pointer;
if (x > this.count)
x = this.count;
T[] result = new T[x];
for (int i = 0; i < x; i++)
{
Previous();
result[i] = Grab();
}
this.Pointer = p;
return result;
}
public T[] GetFirstX(long x)
{
long p = this.Pointer;
if (x > this.count)
x = this.count;
long gap = this.length - this.count;
this.Pointer = (this.Pointer + gap) % this.length;
T[] result = new T[x];
for (int i = 0; i < x; i++)
{
result[i] = Grab();
Next();
}
this.Pointer = p;
return result;
}
public void Clear()
{
this.data = new T[this.length];
this.count = 0;
}
private void Next()
{
this.Pointer++;
if (this.Pointer > this.length - 1)
this.Pointer = 0;
}
private void Previous()
{
this.Pointer--;
if (this.Pointer < 0)
this.Pointer = this.length - 1;
}
private T Grab()
{
return this.data[this.Pointer];
}
public AssemblyLine(long Length)
{
this.length = Length;
this.data = new T[Length];
}
}
Now I am curious if its possible to get that connected to Linq, providing something like this:
AssemblyLine<int> myAssemblyLine = new AssemblyLine(100);
// Insert some Stuff
List<int> myList = myAssemblyLine.Where(i => i > 5).ToList();
Any idea someone?
Almost all LINQ extension methods are declared on IEnumerable<T>, so as soon as your class implements that interface, you'll get it for free.
There are just couple methods that use non-generic IEnumerable, like Cast or OfType, but if you can get your class implement generic IEnumerable<T> it will be much better, because users won't have to call Cast<T> first, to get IEnumerable<T> and access all the other methods (as is right now the case for some legacy collections).
You have to implement IEnumerable<T> for .Where(). See Adding LINQ to my classes.
Once you implement IEnumerable<T> and all required methods, you will have access to these methods: http://msdn.microsoft.com/en-us/library/vstudio/system.linq.enumerable_methods(v=vs.100).aspx
I have a generic class defined like this
class MyGenericClass<T> where T : ICompareable
{
T[] data;
public AddData(T[] values)
{
data = values;
}
}
In mainForm, I create 3 random numbers, and add them as values, lets say 1, 2 and 3. So my T[] data; will look like this: [0]1 [1]2 [2]3
What I want to do is to remove 1 of these values from the array, how do I do that when I'm using generics. Lets say I want to remove 3 from the array so it would look like this[0]1 [1]2
Why don't you use a generic List (List<T>) instead of the array as a private member of your class to hold the data ?
As it is a private member, the 'outside world' cannot access the list, and you will have a much easier life since a List allows you to Add and Remove items easily.
class MyGenericClass<T> where T : ICompareable
{
private List<T> data = new List<T>();
public AddData(params T[] values)
{
data.AddRange (values);
}
public RemoveData( T value )
{
data.Remove (value);
}
public RemoveData( params T[] values )
{
for( int i = 0; i < values.Length; i++ )
{
data.Remove (values[i]);
}
}
}
Once you've done this, you can use the Add member-method of the List to add items, and the Remove member method to remove items. Simple as that.
I've used the params keyword in the AddData method so that you can do this:
var x = new MyGenericClass<int>();
x.AddData(1);
x.AddData(2, 3, 4);
x.AddData(somIntegerList.ToArray());
Change your class to look like this (I also implemented Frederik's suggestion of using a List instead of a array.
class MyGenericClass<T> where T : ICompareable
{
List<T> data;
public AddData(T value)
{
data.Add(value);
}
public RemoveData(T value)
{
data.Remove(value);
}
}
If for some reasaon, you insist on using an array, the remove method may look something like this
public RemoveData(T value)
{
data = data.Where( e => e.CompareTo(value) != 0).ToArray();
}
I kind of had the same question, because I was writing a dynamically sized array to practice creating generic classes.
I found that you can either: move all of the elements down and then set the last element equal to default(T), or create a new array of size-1 to be filled with the remaining elements.
Ex:
public class Array<T>
{
private T[] _array { get; set; }
private int _max { get; set; }
private int _size { get; set; }
public Array()
{
_max = 10;
_array = new T[_max];
_size = 0;
}
public T Remove(int i)
{
if (i >= _size || i < 0) return default(T);
var tmp = _array[i];
for (var j = i; j < _size-1; ++j)
{
_array[j] = _array[j + 1];
}
_array[_size - 1] = default(T);
_size--;
return tmp;
}
}
Or...
public T Remove(int i) {
var tmp = new T[_size-1];
for(var j=0; j < i; ++j)
{
tmp[j] = _array[j];
}
var result = _array[i];
for(var j=i+1; j < _size-1; ++j)
{
tmp[j] = _array[j];
}
_array = null;
_array = tmp;
return result;
}