Not sure of the best alternative to dictionaries in this scenario - objects or arrays.
I need to change the value of the dictionary(or whatever else) depending on whether the id/key exists, adding to the existing value if the id parsed in does exist, never the key/id - what would be the best alternative?
Code
Dictionary<int, int> total = new Dictionary<int, int>();
// elsewhere in a function...
ArrayManager(total, id, value);
public void ArrayManager(Dictionary<int,int> items, int id, int val)
{
int i = 0;
bool found = false;
foreach(var item in items)
{
if(item.Key == id)
{
item.Value += val; // immutable issue stops this from working
found = true;
break;
}
}
if(found == false)
{ // do something }
}
If you're trying to increment the value identified by a given key:
public void ArrayManager(Dictionary<int,int> items, int id, int val)
{
int currentVal = 0;
if (items.TryGetValue(id, out currentVal))
{
int newVal = currentVal + val;
items[id] = newVal;
// Do something else
}
I believe what you are trying to do is:
if(item.Key == id)
{
items[item.Key]+= val;
}
Related
I have a function for stock many string associate to int:
public int Scale(string value)
{
this.stringToInt = new Dictionary<string, int>()
{
{"1p",00},{"2p",01},{"3p",03} ... {"300p",40}
};
// Here i try to do something like that: if(value == (String in dictionary) return associate int
}
So i try to do a comparaison between string receive in enter and string in my dictionary for return associate int.
Any idea?
Thanks you for help !
You can use ContainsKey() method of Dictionary to check if the key is present in dictionary:
if (this.stringToInt.ContainsKey(value)
{
return this.stringToInt[value];
}
else
{
// return something else
}
Another way is to use TryGetValue():
var valueGot = this.stringToInt.TryGetValue(value, out var associate);
if (valueGot)
{
return associate;
}
else
{
// return something else
}
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");
}
}
}
}
I'm trying to solve questions of C# programming in testdome.com, but I found problem about performance. How to solve it?
BinarySearchTree
using System;
public class Node
{
public int Value { get; set; }
public Node Left { get; set; }
public Node Right { get; set; }
public Node(int value, Node left, Node right)
{
Value = value;
Left = left;
Right = right;
}
}
public class BinarySearchTree
{
public static bool Contains(Node root, int value)
{
Console.WriteLine("value=" + value);
if(root == null)
return false;
else if(root.Value == value)
return true;
else if(root.Value != value)
{
return Contains(root.Left, value) | Contains(root.Right, value);
}
return false;
}
public static void Main(string[] args)
{
Node n1 = new Node(1, null, null);
Node n3 = new Node(3, null, null);
Node n2 = new Node(2, n1, n3);
Console.WriteLine(Contains(n2, 3));
}
}
Performance test on a large tree: Memory limit exceeded
https://www.testdome.com/for-developers/solve-question/7482
TwoSum
using System;
using System.Collections.Generic;
class TwoSum
{
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
for(int ctr1=0; ctr1<list.Count; ctr1++)
{
for(int ctr2=0; ctr2<list.Count; ctr2++)
{
if ((ctr1 != ctr2) && (list[ctr1]+list[ctr2] == sum))
return new Tuple<int, int>(ctr1, ctr2);
}
}
return null;
}
public static void Main(string[] args)
{
Tuple<int, int> indices = FindTwoSum(new List<int>() { 1, 3, 5, 7, 9 }, 12);
Console.WriteLine(indices.Item1 + " " + indices.Item2);
}
}
Performance test with a large number of elements: Time limit exceeded
https://www.testdome.com/for-developers/solve-question/8125
For the Binary search tree, testdome.com provides a hint "If a value being searched for is smaller than the value of the node, then the right subtree can be ignored." This cuts memory consumption by half.
public static bool Contains(Node root, int value) {
Console.WriteLine("value=" + value);
if (root == null) {
return false;
}
else if (value == root.Value) {
return true;
}
else if (value < root.Value) {
// Hint 2: If a value being searched for is smaller than the value of the node,
// then the right subtree can be ignored.
return Contains(root.Left, value);
}
else {
return Contains(root.Right, value);
}
return false;
}
For the TwoSum, if we assume that the values in the input array are unique, we can use a dictionary to look up an index by its value (in O(1) time). This relates to the hint "A dictionary can be used to store pre-calculated values, this may allow a solution with O(N) complexity."
// Write a function that, when passed a list and a target sum,
// returns, efficiently with respect to time used,
// two distinct zero-based indices of any two of the numbers,
// whose sum is equal to the target sum.
// If there are no two numbers, the function should return null.
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum) {
if (list.Count < 2) {
return null;
}
// Hint 2: A dictionary can be used to store pre-calculated values,
// this may allow a solution with O(N) complexity.
var indexByValue = new Dictionary<int, int>();
for (var i = 0; i < list.Count; i++) {
var value = list[i];
// ensure that the values used as keys are unique
// this is OK because we only have to return any tuple matching the sum,
// therefore we can ignore any duplicate values
if (!indexByValue.ContainsKey(value)) {
indexByValue.Add(value, i);
}
}
for (var j = 0; j < list.Count; j++) {
var remainder = sum - list[j];
if (indexByValue.ContainsKey(remainder)) {
return new Tuple<int, int> (j, indexByValue[remainder]);
}
}
return null;
}
Simpler way to attack the problem. The above answers are good, but think the desired result can be found quicker.
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
if (list.Count < 2) { return null; }
foreach (int i in list)
{
int result = sum - i;
if(list.Contains(result))
{
return new Tuple<int, int>(i, result);
}
}
return null;
}
For TwoSum, I found the below link that gives 100% pass on TestDome: Look for JonnyT's answer:
TwoSum 100% Pass
Below is the code as well:
PS: I am only providing this to help others, so please upvote JonnyT's answer instead of mine :)
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
HashSet<int> hs = new HashSet<int>();
for (int i = 0; i < list.Count; i++)
{
var needed = sum - list[i];
if (hs.Contains(needed))
{
return Tuple.Create(list.IndexOf(needed), i);
}
hs.Add(list[i]);
}
return null;
}
public static void Main(string[] args)
{
Tuple<int, int> indices = FindTwoSum(new List<int>() { 3, 1, 5, 7, 5, 9 }, 10);
if (indices != null)
{
Console.WriteLine(indices.Item1 + " " + indices.Item2);
}
}
// This passes all tests
public static bool Contains(Node root, int value)
{
var result = false;
if (root == null) return result;
if (value == root.Value)
{
result = true;
}
else
{
if(value <= root.Value)
{
if(Contains(root.Left, value))
{
result = true;
}
}
else
{
return Contains(root.Right, value);
}
}
return result;
}
For Twosum:
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
if (list.Count < 2)
{
return Tuple<int, int>(0,0);
}
for (var j = 0; j < list.Count; j++)
{
var remainder = sum - list[j];
if (list.Contains(remainder))
{
return new Tuple<int, int>(list[j], remainder);
}
}
return new Tuple<int, int>(0,0);
}
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;
}
}
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);
}
}
}