So I have a sparse matrix of elements that is represented as
Dictionary<int, Dictionary<int, StructuredCell>> CellValues = new Dictionary<int, Dictionary<int, StructuredCell>>();
inside a class StructuredTable. I would like to be able to write a loop as
StructuredTable table = new StructuredTable();
// Fill the table with values
foreach(StructuredCell cell in table.Cells()) {
// Fill an alternate structure
}
Where any x,y combination inside the bound of the max of the number of columns and rows is returned as null. I can't seem to locate an example that uses yield this way.
Something like
public IEnumerable<StructuredCell> Cells(){
for (int i = 0; i < maxColumn; i++)
{
Dictionary<int, StructuredCell> row = null;
CellValues.TryGetValue(i, out row);
for (int j = 0; j < maxRow; j++)
{
if (row == null) yield return null;
StructuredCell cell = null;
row.TryGetValue(j, out cell);
yield return cell;
}
}
}
Based on the fact that the keys are resonable small you can do a number of optimizations here.
public class DataStructure {
private const int MAX_VALUE = 100000;
private readonly Dictionary<long, StructuredCell> CellValues;
private void Add(int keyOne, int keyTwo, StructuredCell cell) {
long hashKey = keyOne*MAX_VALUE + keyTwo;
CellValues[hashKey] = cell;
}
private void Remove(int keyOne, int keyTwo)
{
long hashKey = keyOne * MAX_VALUE + keyTwo;
CellValues.Remove(hashKey);
}
private IEnumerable<StructuredCell> GetCells() {
return CellValues.Values;
}
}
You can keep a simple Key->Value dictionary, where the
key = hash(keyOne, keyTwo)
You don't need any fancy lazy constructs (yield) since you already have the values available.
Related
Please check the code below. I am trying to set value to a random property of a int list. Problem is that even after i set 5 to a random list this value getting inserted to that property. What am I doing wrong here?
var TransactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
TransactionList.Add(0);
}
var randTransaction = TransactionList.OrderBy(x => Guid.NewGuid()).FirstOrDefault();
//here i am trying to set 5 value to a random TrnasactionList but this not being set
randTransaction = 5;
Try like below. new Random().Next(0, 59); will return value between 0 and 59. Or you can better set it like new Random().Next(0, TransactionList.Count); for it to be dynamic with list.
new Random().Next(minValue, maxValue); The maxValue for the upper-bound in the Next() method is exclusive—the range includes minValue, maxValue-1, and all numbers in between.
var TransactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
TransactionList.Add(0);
}
// var index = new Random().Next(0, 59);
// Below will work for dynamic length of list.
var index = new Random().Next(0, TransactionList.Count);
TransactionList[index] = 5;
If you don't mind the original list getting sorted you could do this:
class Program
{
static void Main(string[] args)
{
var transactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
//I initialized the list with i instead of 0 to better see sorting in place
transactionList.Add(i);
}
transactionList.Sort(new RandomComparer());
//changed it to 99 to spot it more easily
transactionList[0] = 99;
foreach (var i in transactionList)
Console.WriteLine(i);
}
}
public class RandomComparer : IComparer<int>
{
private Random _random = new Random();
public int Compare(int x, int y)
{
return _random.Next(-1, 2);
}
}
See it in action:
https://dotnetfiddle.net/NKuPdx
randTransaction is "int" data type, which is primitive data type.
if you want to set randTransaction that reflect to it's object, just set the object it self
I was working on a HackerRank practice problem and ran into a interesting error
when finished. This code works on every case except the ones causing it to fail
(and they are all timeout exceptions)
Practice Problem
The short version of the problem is you are given a leaderboard (int[]) and "alice's" scores (int[]) you have to find what place she got for each score in the leaderboard...View the link above for the whole problem.
My Solution
public static int[] climbingLeaderboard(int[] scores, int[] alice)
{
int[] results = new int[alice.Length]; //The array that stores alice's placements for each score
Dictionary<int, List<int>> scoresDict = new Dictionary<int, List<int>>(); //Key = x place (1st, 2nd, etc), the list is all the numbers that are at x place
for(int i = 0; i < alice.Length; i++)
{
List<int> alicePlace = scores.ToList<int>();
//Add the score to the array (converted to list for .Add)
alicePlace.Add(alice[i]);
//Sorts in reverse order to get the new score in the correct place
alicePlace = RecalculateScores(alicePlace);
//Breaks down the scores into the dictionary above
scoresDict = SeperateScores(alicePlace);
//Addes the place to the array
results[i] = GetPlace(scoresDict, alice[i]);
}
return results;
}
//Returns scores[] in reverse SORTED order
public static List<int> RecalculateScores(List<int> scores)
{
List<int> scoresRet = scores;
scoresRet.Sort();
scoresRet.Reverse();
return scoresRet;
}
//Gets the place (key) for where score is in the dict's value list
public static int GetPlace(Dictionary<int, List<int>> dict, int score)
{
foreach (int i in dict.Keys)
{
foreach (int ii in dict[i])
{
if (ii == score)
{
return i;
}
}
}
return -1;
}
//Seperates the array into a dictionary by score placement
public static Dictionary<int, List<int>> SeperateScores(List<int> scores)
{
int placeholder = scores[0];
int currentPlace = 1;
Dictionary<int, List<int>> scoresByPlace = new Dictionary<int, List<int>>();
for (int i = 0; i < scores.Count(); i++)
{
if (scores[i] == placeholder)
{
if (!scoresByPlace.Keys.Contains(currentPlace) || scoresByPlace[currentPlace] == null)
{
scoresByPlace[currentPlace] = new List<int>();
}
scoresByPlace[currentPlace].Add(scores[i]);
placeholder = scores[i];
}
else
{
currentPlace++;
if (!scoresByPlace.Keys.Contains(currentPlace) || scoresByPlace[currentPlace] == null)
{
scoresByPlace[currentPlace] = new List<int>();
}
scoresByPlace[currentPlace].Add(scores[i]);
placeholder = scores[i];
}
}
return scoresByPlace;
}
Error
Whenever it gets tested with a large array amount (2 Million for examples) it returns an timeout exception (probably HackerRank generated to make it harder)
Attempted solution
Believe it or not but I changed a lot of things on the above code. For one,the results array in the first function used to be a list but I changed to array to make it faster. I feel the dictionary/List is slowing everything down but I need them for the solution (Especially the dictionary). Any Help would be appreciated
I have implemented my own selection sort method that seems to be doing it's job for the most part; However, when I am printing files to an excel sheet the printer does not print the first item. I am unsure whether or not the sort method is the source of the problem. My test method for my sort method passes, which is why I am doubting that that is the source. My sort method is shown below. Does it have an error in the scope or order or operations? When I manually move through it on paper everything sorts properly.
public bool sortMaterial()
{
for (int i = 0; i < salesList.Count - 2; i++)
{
Sales curr = salesList[i];
Sales temp;
Sales min = curr;
int swap = 0;
for (int j = i + 1; j < salesList.Count; j++ )
{
temp = salesList[j];
if (String.Compare(temp.material, min.material) == -1)
{
min = temp;
swap = j;
}
}
salesList[i] = min;
salesList[swap] = curr;
}
return true;
}
A neat way to do custom sorting is by implementing the IComparer<T> interface:
public class SalesMaterialComparer : IComparer<Sales> {
public int Compare(Sales x, Sales y) {
return String.Compare(x.material, y.material);
}
}
You can pass your custom comparer to the LINQ OrderBy() method.
IEnumerable<Sales> salesList;
var myComparer = new SalesMaterialComparer();
var sorted = salesList.OrderBy(s => s, myComparer);
I need a data structure with both named column and row. For example:
magic_data_table:
col_foo col_bar
row_foo 1 3
row_bar 2 4
I need to be able to access elements like magic_data_table["row_foo", "col_bar"] (which will give me 3)
I also need to be able to add new columns like:
magic_data_table.Columns.Add("col_new");
magic_data_table["row_foo", "col_new"] = 5;
AFAIK, DataTable only has named column...
EDIT:
I don't need to change the name of a column or a row. However, I may need to insert new rows into the middle of the table.
While you could use a Dictionary<string, Dictionary<string, T>> to do what you want, that wouldn't be particularly efficient in terms of memory, and would have the potential for the inner dictionaries to get out of sync. If you create your own data structure though that is a facade for lists, using dictionaries to map column names to indexes, then it's simple enough:
public class MyDataStructure<T>//TODO come up with better name
{
private Dictionary<string, int> columns;
private Dictionary<string, int> rows;
private List<List<T>> data;
public MyDataStructure(
IEnumerable<string> rows,
IEnumerable<string> columns)
{
this.columns = columns.Select((name, index) => new { name, index })
.ToDictionary(x => x.name, x => x.index);
this.rows = rows.Select((name, index) => new { name, index })
.ToDictionary(x => x.name, x => x.index);
initData();
}
private void initData()
{
data = new List<List<T>>(rows.Count);
for (int i = 0; i < rows.Count; i++)
{
data.Add(new List<T>(columns.Count));
for (int j = 0; j < columns.Count; j++)
{
data[i].Add(default(T));
}
}
}
public T this[string row, string column]
{
//TODO error checking for invalid row/column values
get
{
return data[rows[row]][columns[column]];
}
set
{
data[rows[row]][columns[column]] = value;
}
}
public void AddColumn(string column)
{
columns.Add(column, columns.Count);
for (int i = 0; i < data.Count; i++)
{
data[i].Add(default(T));
}
}
public void AddRow(string row)
{
rows.Add(row, rows.Count);
var list = new List<T>(columns.Count);
data.Add(list);
for (int i = 0; i < columns.Count; i++)
{
list.Add(default(T));
}
}
public bool RenameRow(string oldRow, string newRow)
{
if (rows.ContainsKey(oldRow) && !rows.ContainsKey(newRow))
{
this.Add(newRow, rows[oldRow]);
this.Remove(oldRow);
return true;
}
return false;
}
}
Note that if you were willing to fix the rows/columns upon construction then you'd be able to use a T[,] as the backing for the data, which would both make the class dramatically simpler to implement, and further reduce the memory overhead, although that doesn't appear to work for your use cases.
Add a column for the name - "name" in the following:
DataTable table = ...
DataColumn nameCol = table.Columns["name"];
var index = table.Rows.Cast<DataRow>()
.ToDictionary(row => (string)row[nameCol]);
... // then when you need the values:
string rowName = ..., colName = ...
var val = index[rowName][colName];
You may find that the Tuple (.net 4.0 and above) class suits your needs. It won't work strictly like a table but will give you a lot of flexibility.
You can use the List<> generic to store it and LINQ to query your data.
List<Tuple<string, string, int>> magicTable = new List<Tuple<string, string, int>>();
magicTable.AddRange(new Tuple<string, string, int>[] {
Tuple.Create("row_foo", "col_foo", 1),
Tuple.Create("row_foo", "col_bar", 2),
Tuple.Create("row_bar", "col_foo", 3),
Tuple.Create("row_bar", "col_bar", 4)});
magicTable.Add(Tuple.Create("row_foo", "col_new", 5));
int value = magicTable.Single(tuple => (tuple.Item1 == "row_foo" && tuple.Item2 == "col_new")).Item3;
It is going to be quite resource intensive due to the duplication of row/column names but you do get a lot of flexibility for small datasets.
Microsoft's Tuple documenation (3-tuple): http://msdn.microsoft.com/en-us/library/dd387150.aspx
Something like:
forelement (element G_Element, Grid)
{
Grid[G_Element.dim1, G_Element.dim2] =
new clsGridElement(G_Element.dim1, G_Element.dim2);
}
instead of
for (int X = 0; X < GridWidth; X++)
for (int Y = 0; Y < GridHeight; Y++)
Grid[X, Y] = new clsGridElement(X, Y);
If something doesn't innately exist, is that something that could be created?
Thanks,
Tim
You could do this - just make a custom type that exposes these, and use a regular foreach:
public class TwoDimensionalIterator
{
public TwoDimensionalIterator(int i, int j)
{
this.Dim1 = i; this.Dim2 = j;
}
public int Dim1 { get; private set; }
public int Dim2 { get; private set; }
}
Then make an extension method somewhere to return an enumerable of this:
public static IEnumerable<TwoDimensionalIterator> IterateTwoDim<T>(this T[,] array)
{
for (int i=0;i<array.GetLength(0);++i)
for (int j=0;i<array.GetLength(1);++j)
yield return new TwoDimensionalIterator(i,j);
}
With this, you could then do:
foreach(var index in Grid.IterateTwoDim())
{
Grid[index.Dim1, index.Dim2] = new clsGridElement(index.Dim1, index.Dim2);
}
Not sure exactly what you are trying to do here, or why, or what you expect to get from it, but if you implement your own iterator than implements the IEnumerator interface then you could create something that would hit every cell in your 2D (or more) collection.
Of course, you won't actually gain anything performance-wise from doing this versus just using nested loops, but I guess it'd be syntactic sugar.
Such creation of indexes can be obtained by using "Cartesian product" of all indexes. Here is sample based on Is there a good LINQ way to do a cartesian product? (courtesy of the Eric Lippert):
var allIndexes = from dim1 in Enumerable.Range(0, Grid.GetLength(0))
from dim2 in Enumerable.Range(0, Grid.GetLength(1))
select new {dim1, dim2};
foreach (var G_Element in allIndexes)
{
Grid[G_Element.dim1, G_Element.dim2] =
new clsGridElement(G_Element.dim1, G_Element.dim2);
}