item on an list exists for a limited time - c#

I want a list that would hold a item for a specified time.
This is what I tried for now:
private void digtimer_Tick(object sender, EventArgs e) //Goes off every half a second
{
justmine.Clear();
}
However, this way deletes all of the items after every interval, regardless of how long the items in the list existed. Is there any way so that after an list item exists for a specified time, it is removed?
EDIT: The list is integers only. The newest code is:
` //public static Dictionary<int, DateTime> justmine = new Dictionary<int, DateTime>();
//Adding an item is: justmine.Add(userid, DateTime.Now);
private void digtimer_Tick(object sender, EventArgs e)
{
foreach (KeyValuePair<int, DateTime> pair in justmine)
{
console.Items.Add((DateTime.Now - pair.Value).TotalSeconds).ToString();
string x = ((DateTime.Now - pair.Value).TotalSeconds).ToString();
if ((Convert.ToDouble(x) < 500.0))
{
justmine.Remove(pair.Key);
}
}
}
`
This would of seemed to work, but I am not able to edit the dictionary while the tick is running. EXTRA NOTE This list is now a Dictionary with
public static Dictionary<int, DateTime> justmine = new Dictionary<int, DateTime>();

public class JustMine
{
public string Value { get; set; }
public decimal Milliseconds { get; set; }
public JustMine()
{
this.Milliseconds = DateTime.Now.Ticks / (decimal)TimeSpan.TicksPerMillisecond;
}
}
List<JustMine> JustMine = new List<JustMine>();
var now = DateTime.Now.Ticks / (decimal)TimeSpan.TicksPerMillisecond;
var limit = 5000; // 5 seconds
foreach(var item in JustMine.ToList())
{
if (now - item.Milliseconds >= limit)
{
JustMine.Remove(item);
}
}

This is a two part answer. For one you need the add time. So add a DateTime to your type called Added. Now when you add an item to the list you need to do;
myInstance.Added = DateTime.UtcNow;
justmine.Add(myInstance);
In your digtimer_Tick method, compare the Added value to DateTime.UtcNow like;
if ((DateTime.UtcNow - item.Added).TotalSeconds > lifeTime) {
justmine.Remove(item);
}
Note, better than my suggestion to modify your type is probably the suggestion to use a Tuple<DatTime, YouType> where item1 is just the added time. Do note that tuples are immutable. In general I like it because any type can be used this way, even primitives.
Second note; in digitimer_Tick you could probably do like justmine.Where(x => (DateTime.UtcNow - x.Added).TotalSeconds > lifeTime) and then remove that set from the original collection rather than using a foreach loop.

If you understand type arguments well enough, you can create a class extending List<T>. Hide the Add() method with your own method to:
1. Call base.Add()
2. Call base.Remove() after a certain time (ideally using a Timer. See this thread)
This way you can abstract the work to the class (List) that should be doing the work rather than having a timer doing it.
Edit: As mentioned in a comment, you might also want to consider concurrency/synchronization. There are Collections in System.Collections.Concurrent you might want to consider for what I assume is a multithreaded application you're making. (Note: While this answer does say you should extend List, NEVER try to roll-your-own with concurrency in Collections. Let the resources do that work for you.)

Related

Adding a number to variable names in C#

My question is sort of like the one found here:
How do I name variables dynamically in C#?
However its a bit different so I'm wondering if its possible.
I'm trying to read in a bunch of strings from a .settings file.
I have them all named Time1, Time2,Time3 etc...
I want the User to be able to add more Times to the file so there could be Time100 or more.
I have a Size in the settings file that will keep track of the amount of Time Variables.
I want to write something that will read in all of the Time strings. I think it would be silly to pre-fill the .settings file with 100 Time Variables so I know they are there and then manually read in each one.
So I'm wondering if there is a way where I can read in Timei or Time+i where I is an integer that I can put in a loop that will find them all.
(note that the data is string not time, its just going to be converted to days of the week)
Such as: (Days is from ApplicationSettingsBase [aka file add new Settings1.settings]
public static int AvDaysIndex = Days.Default.Size; //This holds the number of items in Days
public static DayOfWeek[] AvailableDays = new DayOfWeek[AvDaysIndex]; //This is where I wants to read in all the variables Aka Time1 Time2 Times3
public ReadInDays() //Reads in from the .settings File
{
if(AvDaysIndex>0) // Makes sure there is something in Days to read
{
int I=0;
//I can Manually do the following
AvailableDays[I++] = Days.Default.Time1;
AvailableDays[I++] = Days.Default.Time2;
AvailableDays[I++] = Days.Default.Time3; //etc...
//Is there a way to do something like this
for (int i = 0; i < AvDaysIndex; i++) //reads in each time
{
AvailableDays[i] = Days.Default.Time +i;//where I would be added to the variable name to find it?
//Or something like
AvailableDays[i] = Days.Default.Time(I.tostring())
}
}
}
Hopefully all that at least makes it clear what I'm trying to do.
Edit - I'm starting to think my issue is actually with the .settings file. and that if I just read values in from another file type where the values don't have names I can easily read them in even though there is a variable number of elements in the file.
Solution -
for (int i = 0; i < Index; i++)
{
AvailableDays[i] = getFromFile(_Days.Default.Properties["Time" + (i+1).ToString()].DefaultValue.ToString());
AvailableTimes[i] = Convert.ToDateTime(_Times.Default.Properties["Time" + (i + 1).ToString()].DefaultValue);
}
It was all in figuring out how to read in from the .settings file and instead of reading it in directly aka Days.Default.Time1; I had to to do a generic lookup from Days.Default.Properties and then I could create a dynamic name and find it. You guys probably were trying to tell me how to do this, I just didn't understand.
Thanks again to all those that helped.
I would use a hashtable/dictionary to store the Days.Default.TimeX variations
hashtable["Time1"]...hashtable["TimeN"]
As already mentioned a hashtable or a dictionary would probably serve you best. If you go the dictionary route you can create a string/int indexer on the class and you would be able to alter your code slightly:
http://msdn.microsoft.com/en-us/library/2549tw02%28v=vs.80%29.aspx - Example of creating indexer on a class:
Example Indexer Class:
public class Default
{
private Dictionary<int, DayOfWeek> _values = new Dictionary<int,DayOfWeek>();
public DayOfWeek this[int index]
{
get
{
if (_values.ContainsKey(index))
return _values[index];
else
return null;
}
set
{
_values[index] = value;
}
}
}
Original:
AvailableDays[i] = Days.Default.Time(I.tostring())
Would become:
AvailableDays[i] = Days.Default.Time[I];
Reflection is always an option too and i have an example below that is in a Windows Console Application:
public class Default
{
public int Time1 { get; set; }
public int Time2 { get; set; }
public int Time3 { get; set; }
}
class Program
{
static void Main(string[] args)
{
Default d = new Default();
Type t = d.GetType();
foreach (var info in t.GetProperties())
{
//SET VALUE
info.SetValue(d, 1);
}
foreach (var info in t.GetProperties())
{
//GET VALUE
Console.WriteLine("Property: {0}", info.Name);
Console.WriteLine("Value: {0}", info.GetValue(d));
}
//OR JUST ONE PROPERTY
Console.WriteLine("Time1 Property Value: {0}", t.GetProperty("Time1").GetValue(d));
Console.ReadLine();//PAUSE THE CONSOLE AFTER PROCESSING
}
}
In your example using reflection:
Days.Default.GetType().GetProperty("Time" + I.ToString()).GetValue(Days.Default) as DayOfWeek;
Another option could be to use Reflection. And getting the values from the enum on the fly.
See the link: How to Get Enum Values with Reflection in C#
However, using a Dictionary<string, DayOfWeek> will give you better performance and more readable code.
I think you could better resolve your problem by implementing your configuration using a
ConfigurationElementCollection. Then the 'names' of the configuration elements are irrelevant. You enumerate a collection of values and use those directly.
See here for an example; How to implement a ConfigurationSection with a ConfigurationElementCollection.

Is it possible to change an element in a queue?

Let say if I have a queue of integer (or any class T), can I change the value of the element in the queue?
More specifically, if I define the queue as follow:
Queue<int> q = new Queue<int>();
Can we change the value of its element similar to how we deal with an array? (if q were an array, we would be able to do something like this: q[0]=1 to change its element). I just would like to simplify the scenario and use int as example, but my intention was trying to peek at the 1st item of a class T in a queue, do some calculations and update the queue for other programs to process. I do not want to dequeue it because it the sequence in the queue will then not be the same as the original. Hope what am trying to do make sense. Please advise.
If the item in the queue was a mutable type then you could change the value that the queue has as it's first item. Without re-creating the queue, or performing a lot of enqueues/dequeues there is no way to change which item is at the front of the queue.
As an example of the first case, if you had a Queue<MyClass> with a definition of:
class MyClass
{
public string Value { get; set; }
}
Queue<MyClass> queue = new Queue<MyClass>();
queue.Enqueue(new MyClass() { Value = "1" });
queue.Peek().Value = 2;
string value = queue.Peek().Value; // is 2
You can't directly change an item in Queue (although you can use a workaround as Tudor suggested). But if you want to have a queue, you don't have to use Queue. Another possible type from .Net is LinkedList. It allows you to add and remove things from both ends, which can be used in your scenario:
LinkedList<int> list = new LinkedList<int>();
// enqueue an item
list.AddLast(1);
// dequeue an item
var item = list.First.Value;
list.RemoveFirst();
// put item back to the front of the queue
list.AddFirst(item);
It seems you want to do this to process each item by several modules in sequence. But I'm not sure this is the right way to do this kind of work. A better way might be to have a queue between each two modules. A module would always take an item from its input queue, process it and then put it in its output queue.
One of the advantages of this approach is greater flexibility: a module can have different type on the output than on the input, which is not possible with the “one queue” approach (unless you resort to having a queue of objects, or something like that).
TPL Dataflow (new in .Net 4.5) uses this approach to improve performance through parallelization. It can do that, because each module can process items independently of other modules if you don't have a single central queue.
As long as you're storing a reference type like a class, any changes you make to it will be reflected in the Queue. The output of the code below will be "2":
public class MyClass
{
public int Value { get; set; }
}
static void Main(string[] args)
{
Queue<MyClass> q = new Queue<MyClass>();
q.Enqueue(new MyClass { Value = 1 });
var i = q.Peek();
i.Value++;
i = q.Peek();
Console.WriteLine(i.Value);
}
You could use a simple wrapper:
class Wrapper<T>
{
public T Value { get; set; }
}
static void Main(string[] args)
{
Queue<Wrapper<int>> q = new Queue<Wrapper<int>>();
Wrapper<int> wr = new Wrapper<int> { Value = 1 };
q.Enqueue(wr);
Wrapper<int> wr1 = q.Peek();
wr1.Value = 2;
int value = q.Dequeue().Value;
Console.WriteLine(value);
}
public static class Extensions
{
public static Queue<T> SetFirstTo<T>(this Queue<T> q, T value)
{
T[] array = q.ToArray();
array[0] = value;
return new Queue<T>(array);
}
}
Strictly this is not mutating the Queue so re-assignment required.
[TestMethod]
public void Queue()
{
var queue = new Queue<int>(new[]{1,2,3,4});
queue = queue.SetFirstTo(9);
Assert.AreEqual(queue.Peek(),9);
}
The simple answer is no. It's not part of the API of Queue object
http://msdn.microsoft.com/en-us/library/system.collections.queue.aspx
However anything is possible of course. You could write an extension method to do this, but it would have to work with the API of the object and so dequeue / enqueue all items along with the change whilst preserving the order.
But if you want to do this, you are treating the Queue as a List, so why not use a List?

Merge 2 sorted time series algorithm

I have 2 time series that contain Bar objects, each Bar object contains a member variable of type long and each time series is stored within its own BlockingCollection. The time series is sorted in ascending order of the long values.
I like to devise a merge algorithm that allows me to take away the Bar that contains the long member variable of lowest value relative to the same comparison element in the other BlockingCollection.
Example, if the long value contained in the first Bar (bar1) in BlockingCollection1 is lower than the long value contained in the first Bar (bar2) in BlockingCollection2, then Take() from BlockingCollection1 and Add() to a MasterBlockingCollection, essentially ending up with a merged stream of Bar objects sorted by the value of each Bar's long member variable.
I like to later on extend to n BlockingCollections, not just 2. I played around with arrays that hold the long values to make the mapping easier but I think arrays are handier when working with pointers pertaining to this specific target algorithm.
I wonder whether anyone can point me to a Linq implementation and comment on how computationally expensive such approach is. I am asking because throughput is of importance as there are hundreds of millions of Bar objects flowing through the collections. If someone has a more clever idea than using Linq that would be very welcomed. I came across some ideas re merge algorithm at DrDobbs some time ago but cannot find the article anymore. In case it is not apparent by now, I target C# (.Net4.0)
Thanks a lot
Edit: I forgot to mention that the merging process is supposed to happen at the same time than workers who add new items to the blockingcollections (running on different tasks)
Here's an implementation of Merge. It should run in O(cN) time, where c is the number of collections. Is this what you're looking for?
public static BlockingCollection<Bar> Merge(IEnumerable<BlockingCollection<Bar>> collections)
{
BlockingCollection<Bar> masterCollection = new BlockingCollection<Bar>();
LinkedList<BarWrapper> orderedLows = new LinkedList<BarWrapper>();
foreach (var c in collections)
OrderedInsert(new BarWrapper { Value = c.Take(), Source = c }, orderedLows);
while (orderedLows.Any())
{
BarWrapper currentLow = orderedLows.First.Value;
orderedLows.RemoveFirst();
BlockingCollection<Bar> collection = currentLow.Source;
if (collection.Any())
OrderedInsert(new BarWrapper { Value = collection.Take(), Source = collection }, orderedLows);
masterCollection.Add(currentLow.Value);
}
return masterCollection;
}
private static void OrderedInsert(BarWrapper bar, LinkedList<BarWrapper> orderedLows)
{
if (!orderedLows.Any())
{
orderedLows.AddFirst(bar);
return;
}
var iterator = orderedLows.First;
while (iterator != null && iterator.Value.Value.LongValue < bar.Value.LongValue)
iterator = iterator.Next;
if (iterator == null)
orderedLows.AddLast(bar);
else
orderedLows.AddBefore(iterator, bar);
}
class BarWrapper
{
public Bar Value { get; set; }
public BlockingCollection<Bar> Source { get; set; }
}
class Bar
{
public Bar(long l)
{
this.LongValue = l;
}
public long LongValue { get; set; }
}

ArrayList retrieving value of object

This is getting made in a static void method in the main class. (class being used for input).
private static void Input(ArrayList list)
{
//other code...
Object b = new Object(number, hour, minutes, seconds);
list.Add(b)
}
Next I have another static void method to display the objects within.
The thing is i want to group them on the number, and then display all the hours, minutes and seconds for the same number underneath each other.
Then the following number(s) with all there corresponding hours, minutes and seconds.
But I am not sure how i can get the number for example the first array, and 2nd and so on.
How can I access this? The syntax below does not work and not sure how to retrieve this value(s).
int var = array[0].number; //does not work
Also how do i make a instance of this object again? I cannot use new again can i?
private static void Output(ArrayList list)
{
while (i < list.Count)
{
//keep track of current group (number)
//announce group
//...
}
}
Regards.
This is because you're using a non-generic collection (ArrayList instead of List<T>). If you can, it would be much better to use a generic collection. However, if you're forced to use ArrayList, you've got to cast:
Foo foo = (Foo) list[0];
int x = foo.number;
...
(I hope you haven't really named your own class Object... I would also recommend against using the name var as that is a contextual keyword as of C# 3.)
Instead of using an ArrayList, use a List<T> where T is your type of object.

Generating the next available unique name in C#

If you were to have a naming system in your app where the app contains say 100 actions, which creates new objects, like:
Blur
Sharpen
Contrast
Darken
Matte
...
and each time you use one of these, a new instance is created with a unique editable name, like Blur01, Blur02, Blur03, Sharpen01, Matte01, etc. How would you generate the next available unique name, so that it's an O(1) operation or near constant time. Bear in mind that the user can also change the name to custom names, like RemoveFaceDetails, etc.
It's acceptable to have some constraints, like restricting the number of characters to 100, using letters, numbers, underscores, etc...
EDIT: You can also suggest solutions without "filling the gaps" that is without reusing the already used, but deleted names, except the custom ones of course.
I refer you to Michael A. Jackson's Two Rules of Program Optimization:
Don't do it.
For experts only: Don't do it yet.
Simple, maintainable code is far more important than optimizing for a speed problem that you think you might have later.
I would start simple: build a candidate name (e.g. "Sharpen01"), then loop through the existing filters to see if that name exists. If it does, increment and try again. This is O(N2), but until you get thousands of filters, that will be good enough.
If, sometime later, the O(N2) does become a problem, then I'd start by building a HashSet of existing names. Then you can check each candidate name against the HashSet, rather than iterating. Rebuild the HashSet each time you need a unique name, then throw it away; you don't need the complexity of maintaining it in the face of changes. This would leave your code easy to maintain, while only being O(N).
O(N) will be good enough. You do not need O(1). The user is not going to click "Sharpen" enough times for there to be any difference.
I would create a static integer in action class that gets incremented and assigned as part of each new instance of the class. For instance:
class Blur
{
private static int count = 0;
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
public Blur()
{
_name = "Blur" + count++.ToString();
}
}
Since count is static, each time you create a new class, it will be incremented and appended to the default name. O(1) time.
EDIT
If you need to fill in the holes when you delete, I would suggest the following. It would automatically queue up numbers when items are renamed, but it would be more costly overall:
class Blur
{
private static int count = 0;
private static Queue<int> deletions = new Queue<int>();
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
Delete();
}
}
private int assigned;
public Blur()
{
if (deletions.Count > 0)
{
assigned = deletions.Dequeue();
}
else
{
assigned = count++;
}
_name = "Blur" + assigned.ToString();
}
public void Delete()
{
if (assigned >= 0)
{
deletions.Enqueue(assigned);
assigned = -1;
}
}
}
Also, when you delete an object, you'll need to call .Delete() on the object.
CounterClass Dictionary version
class CounterClass
{
private int count;
private Queue<int> deletions;
public CounterClass()
{
count = 0;
deletions = new Queue<int>();
}
public string GetNumber()
{
if (deletions.Count > 0)
{
return deletions.Dequeue().ToString();
}
return count++.ToString();
}
public void Delete(int num)
{
deletions.Enqueue(num);
}
}
you can create a Dictionary to look up counters for each string. Just make sure you parse out the index and call .Delete(int) whenever you rename or delete a value.
You can easily do it in O(m) where m is the number of existing instances of the name (and not dependent on n, the number of items in the list.
Look up the string S in question. If S isn't in the list, you're done.
S exists, so construct S+"01" and check for that. Continue incrementing (e.g. next try S+"02" until it doesn't exist.
This gives you unique names but they're still "pretty" and human-readable.
Unless you expect a large number of duplicates, this should be "near-constant" time because m will be so small.
Caveat: What if the string naturally ends with e.g. "01"? In your case this sounds unlikely so perhaps you don't care. If you do care, consider adding more of a suffix, e.g. "_01" instead of just "01" so it's easier to tell them apart.
You could do something like this:
private Dictionary<string, int> instanceCounts = new Dictionary<string, int>();
private string GetNextName(string baseName)
{
int count = 1;
if (instanceCounts.TryGetValue(baseName, out count))
{
// the thing already exists, so add one to it
count++;
}
// update the dictionary with the new value
instanceCounts[baseName] = count;
// format the number as desired
return baseName + count.ToString("00");
}
You would then just use it by calling GetNextName(...) with the base name you wanted, such as
string myNextName = GetNextName("Blur");
Using this, you wouldn't have to pre-init the dictionary.
It would fill in as you used the various base words.
Also, this is O(1).
I would create a dictionary with a string key and a integer value, storing the next number to use for a given action. This will be almost O(1) in practice.
private IDictionary<String, Int32> NextFreeActionNumbers = null;
private void InitializeNextFreeActionNumbers()
{
this.NextFreeActionNumbers = new Dictionary<String, Int32>();
this.NextFreeActionNumbers.Add("Blur", 1);
this.NextFreeActionNumbers.Add("Sharpen", 1);
this.NextFreeActionNumbers.Add("Contrast", 1);
// ... and so on ...
}
private String GetNextActionName(String action)
{
Int32 number = this.NextFreeActionNumbers[action];
this.NextFreeActionNumbers[action] = number + 1;
return String.Format("{0} {1}", action, number);
}
And you will have to check against collisions with user edited values. Again a dictionary might be a smart choice. There is no way around that. What ever way you generate your names, the user can always change a existing name to the next one you generate unless you include all existing names into the generation schema. (Or use a special character that is not allowed in user edited names, but that would be not that nice.)
Because of the comments on reusing the holes I want to add it here, too. Don't resuse the holes generated be renaming or deletion. This will confuse the user because names he deleted or modified will suddenly reappear.
I would look for ways to simplify the problem.
Are there any constraints that can be applied? As an example, would it be good enough if each user can only have one (active) type of action? Then, the actions could be distinguished using the name (or ID) of the user.
Blur (Ben F)
Blur (Adrian H)
Focus (Ben F)
Perhaps this is not an option in this case, but maybe something else would be possible. I would go to great lengths in order to avoid the complexity in some of the proposed solutions!
If you want O(1) time then just track how many instances of each you have. Keep a hashtable with all of the possible objects, when you create an object, increment the value for that object and use the result in the name.
You're definitely not going to want to expose a GUID to the user interface.
Are you proposing an initial name like "Blur04", letting the user rename it, and then raising an error message if the user's custom name conflicts? Or silently renaming it to "CustomName01" or whatever?
You can use a Dictionary to check for duplicates in O(1) time. You can have incrementing counters for each effect type in the class that creates your new effect instances. Like Kevin mentioned, it gets more complex if you have to fill in gaps in the numbering when an effect is deleted.

Categories

Resources