Overwriting an array entry when it has a duplicate key - c#

I'm writing a small programm right now in which I made a Paar class, where one object consists of a key and a value
class Paar
{
private object value1;
public Paar(string key, object value1)
{
this.key = key;
this.value = value1;
}
public string key;
public object value;
}
I made a Put and a Get method for the class. The Put method parses a new entry in the first open slot it finds and the Get method can be used to print an entry by calling the key, they're as following
private Paar[] getArray = new Paar[10];
public void Put(string key, object value)
{
int i = 0;
while (true)
{
if (getArray[i] == null)
{
break;
}
else
{
i++;
if (i == 10)
{
throw new Exception("All slots full");
}
}
}
getArray[i] = new Paar(key, value);
}
public object Get(string key)
{
for (int i = 0; i <= 9; i++)
{
Paar currentElement = getArray[i]
if (currentElement.key == key)
{
return currentElement.value;
}
}
throw new Exception("Invalid key");
}
"Problem" is, that when I have two entries with the same key, I can only print the first entry, while I'd like to add a function to the Put method that overwrites previous entries with the same key and prints the most recent entry.
E.g:
newMap.Put("Key2", "Value1"); newMap.Put("Key2", "Value2"); newMap.Put("Key2", "Value3");
Console.WriteLine(newMap.Get("Key2"));
would currently print Value1, while I'd like it to print Value3. Is there any way to achieve this?

Try following
public void Put(string key, object value)
{
for (var i = 0; i < getArray.Length; ++i)
{
if (getArray[i] == null || getArray[i].key == key)
{
getArray[i] = new Paar(key, value);
break;
}
if(i == getArray.Length - 1)
throw new Exception("All slots full");
}
}

I implemented tchelidze's answer since it was technically correct, but when later implementing a Remove method it didn't work properly all the time since it could also parse the duplicate key's entry into an empty slot if there happened to be one before the duplicate key's slot, because it either checked for an empty slot or a matching key. So I improved the function to go through two seperate loops.
public void Put(string key, object value)
{
for (int i = 0; i < getArray.Length; i++)
{
if (getArray[i] != null && getArray[i].key == key)
{
getArray[i] = new Paar(key, value);
return;
}
}
for (int i = 0; i < getArray.Length; i++)
{
if (getArray[i] == null)
{
getArray[i] = new Paar(key, value);
break;
}
else
{
if (i >= getArray.Length)
{
throw new Exception("All slots full");
}
}
}
}

Related

Need help understanding a code

so this program I'm on has sprites. Each sprite has a limit to the number of frames its sprite can have, and I'm trying to figure out how to learn that limit so I can modify it. But the code that I've been reading is really difficult for me. I've been reading up on some of the stuff it uses (like Dictionary and Out), but when I try to apply that reading to the code, it just falls apart.
So uh, if someone would be willing to kind of dissect the code and tell me what it says, that would be great. The full of it can be found here, but this is what I'm trying to read in particular:
class FrameData {
Dictionary<FrameType, Dictionary<Enums.Direction, int>> frameCount;
}
public FrameData() {
frameCount = new Dictionary<FrameType, Dictionary<Enums.Direction, int>>();
}
public void SetFrameCount(FrameType type, Enums.Direction dir, int count) {
if (frameCount.ContainsKey(type) == false) {
frameCount.Add(type, new Dictionary<Enums.Direction, int>());
}
if (frameCount[type].ContainsKey(dir) == false) {
frameCount[type].Add(dir, count);
} else {
frameCount[type][dir] = count;
}
}
public int GetFrameCount(FrameType type, Enums.Direction dir) {
Dictionary<Enums.Direction, int> dirs = null;
if (frameCount.TryGetValue(type, out dirs)) {
int value = 0;
if (dirs.TryGetValue(dir, out value)) {
return value;
} else {
return 0;
}
} else {
return 0;
}
}
//This bit declares the class. note that all the stuff after it should come inside the open and closed curly braces, so there's already a syntax error here.
class FrameData {
Dictionary<FrameType, Dictionary<Enums.Direction, int>> frameCount;
}
// Public parameterless constructor. This gets called when someone creates an instance of the class, e.g. FrameData myframe = new FrameData()
public FrameData() {
// initialize the instance variable frameCount with a new dictionary that takes a FrameType as the key and another dictionary of Enums.Direction and ints as key and value
frameCount = new Dictionary<FrameType, Dictionary<Enums.Direction, int>>();
}
// Public method for adding or replacing a key and its value in the frameCount dictionary
public void SetFrameCount(FrameType type, Enums.Direction dir, int count) {
// adds a new one if it didn't already have that key
if (frameCount.ContainsKey(type) == false) {
frameCount.Add(type, new Dictionary<Enums.Direction, int>());
}
// adds a new key to the inner dictionary if it's not there
if (frameCount[type].ContainsKey(dir) == false) {
frameCount[type].Add(dir, count);
} else {
// otherwise just replaces what was already there
frameCount[type][dir] = count;
}
}
// fetches the nested value from the inner dictionary given the type and direction
public int GetFrameCount(FrameType type, Enums.Direction dir) {
Dictionary<Enums.Direction, int> dirs = null;
if (frameCount.TryGetValue(type, out dirs)) {
int value = 0;
if (dirs.TryGetValue(dir, out value)) {
return value;
} else {
return 0;
}
} else {
return 0;
}
}

Pointer in C# reset's after leaving a Class

I have a class Form1 and a class MyList. I want to create a program that puts character into List and has a pointer that shows on next one.
My problem is that everytime when I call class MyList, the pointer resets.
How can I solve the problem.
It is a school project an it must be done on this way, with pointers.
Thanks for all answers!
namespace Data {
public partial class Form1 : Form
{
char character = "a"
int index = 0;
MyList a = new MyList();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) //On click get new index and character and put in a List.
{
a.PutIn(index, character);
}
}
}
MyList class:
namespace Data
{
public unsafe struct list
{
public char x;
public list* next;
}
public unsafe partial class MyList
{
list* first = null;
list* last = null;
int index;
public unsafe MyList() { Initialize(); }
public unsafe void Initialize()
{
first = null;
last = null;
index = -1;
}
~MyList()
{
do{
Emty(0);
}while (!IsEmpty());
}
public unsafe void PutIn(int place, char character)
{
if (((index+1)<place)||(place<0))
MessageBox.Show("Index is too high!");
else
{
if (IsEmpty())
{
list temp = new list();
list* temp_pointer = &temp;
temp_pointer->next = null;
temp_pointer->x = character;
first = temp_pointer;
last = temp_pointer;
temp_pointer = null;
index++;
}
else if (place == (index + 1))
{
list temp = new list();
list* temp_pointer = &temp;
temp_pointer->next = null;
temp_pointer->x = character;
last->next = temp_pointer;
last = temp_pointer;
temp_pointer = null;
index++;
}
}
}
}
The problem is that you are allocating list as a local and it is not guaranteed to last any longer than the scope in which it is defined (in fact, the guarantee only makes sense for managed code anyway - the runtime compiler can get rid of it long before the scope ends if it wants to).
You really want to allocate the object somewhere where it will last a bit longer. The simplest approach is to use Marshal.AllocHGlobal to allocate a bit of memory on the unmanaged heap. You free that memory using Marshal.FreeHGlobal. This is roughly equivalent to using new and delete in C.
I started with your code sample, but had to change a few things to avoid going mad. This doesn't mean that the final sample is 100% correct or a good way of implementing this, I was still only changing a few things in your code to make it work. In a real implementation, I'd make the whole thing a bit differently - if you're interested in some good practices for working with C# and pointers in C# (or in general), you might want to post your full, working code to Code Review - you'll get a lot of good feedback there.
Sample code, including adding and removing items from the list:
void Main()
{
var list = new MyList();
list.InsertAt(0, 'A');
list.InsertAt(1, 'B');
list.InsertAt(2, 'C');
list.InsertAt(1, 'X');
Console.WriteLine(string.Join(", ", list.Select(i => i.ToString())));
list.RemoveAt(1);
Console.WriteLine(string.Join(", ", list.Select(i => i.ToString())));
}
public unsafe struct list
{
public char x;
public list* next;
}
public unsafe class MyList : IEnumerable<char>
{
list* first;
list* last;
int count;
public int Count { get { return count; } }
public bool IsEmpty() { return count == 0; }
private void Remove(list* previous, list* current)
{
if (first == current) first = current->next;
if (last == current) last = previous;
if (previous != null) previous->next = current->next;
Console.WriteLine
(
"Removing {0}, first {1}, last {2}, count {3}",
current->x,
first == null ? '-' : first->x,
last == null ? '-' : last->x,
count
);
count--;
Marshal.FreeHGlobal(new IntPtr(current));
}
public void RemoveAt(int index)
{
if (count < index || index < 0)
throw new ArgumentOutOfRangeException("Index is out of range!");
var current = first;
if (index == 0)
{
Remove(null, current);
return;
}
for (var i = 0; i < index - 1; i++)
{
current = current->next;
}
Remove(current, current->next);
}
~MyList()
{
do
{
RemoveAt(0);
}
while (!IsEmpty());
}
private list* InsertAfter(list* previousItem, char character)
{
var newItem = (list*)Marshal.AllocHGlobal(sizeof(list));
newItem->next = previousItem == null ? null : previousItem->next;
newItem->x = character;
if (previousItem == last) last = newItem;
if (previousItem != null) previousItem->next = newItem;
count++;
Console.WriteLine
(
"Added {0} after {1}, first {2}, last {3}, count {4}",
character,
previousItem == null ? '-' : previousItem->x,
first == null ? '-' : first->x,
last == null ? '-' : last->x,
count
);
return newItem;
}
public void InsertAt(int index, char character)
{
if (count < index || index < 0)
throw new ArgumentOutOfRangeException("Index is out of range!");
if (index == 0)
{
var newItem = InsertAfter(null, character);
if (first != null) newItem->next = first;
first = newItem;
}
else if (index == 1)
{
InsertAfter(first, character);
}
else if (index == count)
{
InsertAfter(last, character);
}
else
{
var current = first;
for (var i = 0; i < index - 2; i++)
{
current = current->next;
}
InsertAfter(current, character);
}
}
private class MyListEnumerator : IEnumerator<char>
{
private MyList list;
private list* current;
public MyListEnumerator(MyList list)
{
this.list = list;
this.current = null;
}
public void Reset() { current = null; }
public bool MoveNext()
{
if (current == null) current = list.first;
else current = current->next;
return current != null;
}
public char Current
{
get
{
if (current == null) throw new InvalidOperationException();
return current->x;
}
}
object IEnumerator.Current { get { return (object)Current; } }
public void Dispose() {}
}
public IEnumerator<char> GetEnumerator() { return new MyListEnumerator(this); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}

In memory cache with multiple keys

I need to build a cache of one of my custom class objects(security as in finance). The object of the class can be identified in multiple ways since it has multiple identifiers like PKey, Name, Long Name, or any other type of name in different language.
So the cache should be searchable on the basis of any of the identifiers i.e. multiple keys.
How can I create such a cache?
I am using C# 4.5 but I think this is a generic problem, so solutions in any way can help
One of the solutions which I think is fast and efficient is to keep different caches for different identifiers. For e.g. < Name,Pkey>, < Long Name,Pkey>, < identifier,Pkey> and a single cache with objects of type < Pkey,Object>
Are there newer and better ways to do this?
Edit: When I am accessing the cache all the keys are not known, so I
can not make a composite key
Maybe this code will be useful:
public class Test12 {
static Map<CacheKey, SecureObject> cache = new ConcurrentHashMap<CacheKey, SecureObject>();
public static void main(String[] args) {
SecureObject secureObject = new SecureObject(new CacheKey("pkey1", "name1", 1L));
cache.put(secureObject.getKey(), secureObject);
secureObject = new SecureObject(new CacheKey("pkey1", "name2", 2L));
if (cache.containsKey(secureObject.getKey())) {
System.out.println("Already in cache.");
}
}
}
class CacheKey {
String pkey;
String name;
Long longName;
CacheKey(String pkey, String name, Long longName) {
this.pkey = pkey;
this.name = name;
this.longName = longName;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CacheKey cacheKey = (CacheKey) o;
if (pkey != null && pkey.equals(cacheKey.pkey)) {
return true;
} else {
if (name != null && name.equals(cacheKey.name)) {
return true;
} else {
if (longName != null && longName.equals(cacheKey.longName)) {
return true;
} else {
return false;
}
}
}
}
#Override
public int hashCode() {
int result = 0;
if (pkey != null) {
result = pkey.hashCode();
} else if (name != null) {
result = name.hashCode();
} else if (longName != null) {
result = longName.hashCode();
}
return result;
}
}
class SecureObject {
CacheKey key;
SecureObject(CacheKey key) {
this.key = key;
}
public CacheKey getKey() {
return key;
}
public void setKey(CacheKey key) {
this.key = key;
}
}
Prints:
Already in cache.
This is not complete solution. This is direction only.

C# - Dictionary with Behaviour of a Ring List?

I need a ring list dictionary that can store key and item. Capacity = 50 and when I add #51 the first item must be removed. Basically it must be a dictionary that behaves like a ring list.
Is there something in .NET Framework that can do that ? Or do I have to write it by myself ?
You won't find anything built-in I think but you can easily implement one using OrderedDictionary
OrderedDictionary maintains items in order which they are inserted. Whenever you reach the limit/capacity you can remove the first item.
or use an extension method :
EDIT :
because
latest added entry ends up being returned first.
so
u can remove the first item like :
dictionary.Remove(dictionary.Last().Key);
& so your extension method is :
addExtension(this Dictionary<string, object> dictionary, string key, object value)
{
if(dictionary.Count == 50)
dictionary.Remove(dictionary.Last().Key);
dictionary.Add(key, value);
}
Try this:
class Program
{
static void Main(string[] args)
{
var rD = new RingDictionary(50);
for (int i = 0; i < 75; i++)
{
rD.Add(i, i);
}
foreach (var item in rD.Keys)
{
Console.WriteLine("{0} {1}", item, rD[item]);
}
}
}
class RingDictionary : OrderedDictionary
{
int indexKey;
int _capacity = 0;
public int Capacity
{
get { return _capacity; }
set
{
if (value <= 0)
{
var errorMessage = typeof(Environment)
.GetMethod(
"GetResourceString",
System.Reflection.BindingFlags.Static |
System.Reflection.BindingFlags.NonPublic,
null,
new Type[] { typeof(string) },
null)
.Invoke(null, new object[] {
"ArgumentOutOfRange_NegativeCapacity"
}).ToString();
throw new ArgumentException(errorMessage);
}
_capacity = value;
}
}
public RingDictionary(int capacity)
{
indexKey = -1;
Capacity = capacity;
}
public new void Add(object key, object value)
{
indexKey++;
if (base.Keys.Count > _capacity)
{
for (int i = base.Keys.Count-1; i >Capacity-1 ; i--)
{
base.RemoveAt(i);
}
}
if (base.Keys.Count == _capacity)
{
base.RemoveAt(indexKey % _capacity);
base.Insert(indexKey % _capacity, key, value);
}
else
{
base.Add(key, value);
}
}
}

Declaring Inner dictionary comparer C#

I have a dictionary as follows
Dictionary<ulong, Dictionary<byte[], byte[]>> Info;
And the inner dictionary holds a byte[] array as a key.
I am unable to understand how to declare the constructor for a the Info dictionary. For the inner key comparison I have ByteArrayComparer,
public class ByteArrayComparer : IEqualityComparer<byte[]>
{
public bool Equals(byte[] left, byte[] right)
{
if (left == null || right == null)
{
return left == right;
}
if (left.Length != right.Length)
{
return false;
}
for (int i = 0; i < left.Length; i++)
{
if (left[i] != right[i])
{
return false;
}
}
return true;
}
public int GetHashCode(byte[] key)
{
if (key == null)
throw new ArgumentNullException("key");
int sum = 0;
foreach (byte cur in key)
{
sum += cur;
}
return sum;
}
}
Which I picked up from SO Here
Please advise
The specification for the comparer wouldn't be part of the Info initialization directly - it would be when you create a value to put in the outer dictionary. For example:
// It's stateless, so let's just use one of them.
private static readonly IEqualityComparer<byte[]> ByteArrayComparerInstance
= new ByteArrayComparer();
Dictionary<ulong, Dictionary<byte[], byte[]>> Info
= new Dictionary<ulong, Dictionary<byte[], byte[]>();
....
...
Dictionary<byte[], byte[]> valueMap;
if (!Info.TryGetValue(key, out valueMap))
{
valueMap = new Dictionary<byte[], byte[]>(ByteArrayComparerInstance);
Info[key] = valueMap;
}
...
When created your Info doesn't have any dictionaries inside so u can't realy define comparere at that step. You have to do this for each item added into Info object.

Categories