Linking data in from two lists in c# - c#

i have information that i have put into two list from a database,
the first list takes in a node object which has attributes ID, LAT and LONG.
Second list has multiple key and values for the each ID in the first list.
the images below illustrate my explanation better.
what I am trying to do is add all those key and values on to the first list for each ID. Any help on how to go about this would be much appreciated.
the information i have put into the two lists. also these are two lists of objects.
Image of things in first list
Image of things in second list
Essentially one list has primary keys from a table, the second list as foreign keys.
i want to add the second list to the first in one line
e.g
ID,LAT,LONG,[KEY,VALUE],[KEY,VALUE].... depending on how many there are

I'm not sure if you're looking for:
(1) a SQL query that returns a table in the format ID, LAT, LONG, [KEY, VALUE], ... or
(2) a way to relate the data in these two tables using C# objects.
I'm going to assume the latter.
You could put all those key-value pairs in a Dictionary<string, string> inside a Node class.
public class Node
{
public long ID { get; }
public int Latitude { get; }
public int Longitude { get; }
public Dictionary<string, string> KeyValuePairs { get; }
}
public class KeyValuePair
{
public long NodeID { get; }
public string Key { get; }
public string Value { get; }
}
And then iterate through both lists adding the key-value pairs to the Dictionary.
// Let's suppose we got these populated from the DB
var nodeList = new List<Node>();
var keyValuePairs = new List<KeyValuePair>();
// If we get too many rows from the DB, we'll get better performance by ordering the lists
var orderedNodesArray = nodeList.OrderBy(n => n.ID).ToArray();
var orderedKVPairsArray = keyValuePairs.GroupBy(kv => kv.NodeID).OrderBy(g => g.Key).ToArray();
var i = 0;
var j = 0;
while (i < orderedNodesArray.Length && j < orderedKVPairsArray.Length)
{
var node = orderedNodesArray[i];
var kvPair = orderedKVPairsArray[j];
if (node.ID < kvPair.Key) i++;
else if (node.ID > kvPair.Key) j++;
else
{
foreach (var kv in kvPair)
node.KeyValuePairs.Add(kv.Key, kv.Value);
i++;
j++;
}
}

Related

Iterate over list inside a dictionary but 1 item from every list at a time

I have a dictionary Dictionary<string, List<string>> MatrixColumns whose content looks like this:
Now, I want to iterate over MatrixColumns Dictionary in such a way that I first get "condition#1" of [0] of key "OPERATOR_ID" and then "delta#1" of [0] of key "DELTA_ID"
and then again "condition#1" of 1 of key "OPERATOR_ID" and then "delta#1" of 1 of key "DELTA_ID" and so on.
Thing to keep in mind is the count of elements inside MatrixColumns can vary and it's not always 2. pls. guide me, How Can I achieve this?
Create a class:
public class MatrixColumnDto
{
public string ColumnName { get; set; }
public List<string> ColumnValues { get; set; }
}
Use LINQ as:
var MatrixColumnsResult = Enumerable.Range(0, MatrixColumns.Max(list
=> list.ColumnValues.Count))
.Select(i => MatrixColumns.Select(list => list.ColumnValues.ElementAtOrDefault(i)).ToList())
.ToList();

Fastest way of comparing two lists without using nested loops

I have two types:
public class SubCategories
{
public static List<SubCategories> subCategories = new List<SubCategories>();
public string title { get; set; }
public string IDfromCategories { get; set; }
public string subCategoryID { get; set; }
public bool isChecked { get; set; }
}
public class UserInsideCategories
{
public string userEmail { get; set; }
public string iDfromSubCategories { get; set; }
}
And two lists both containing this object multiple times.
Now I wanna go through a list with type SubCategories and check each object, if it contains the same value as my other list of type UserInsideCategories. Specifically, I wanna know if any object on the list.SubcategoryID is equal to any object on the other list.IdFromSubCateogires.
I achieved this like so:
List<SubCategories> branch = new List<SubCategories>();
for(int i = 0; i < subCategories.Count; i++)
{
SubCategories e = new SubCategories();
for(int x = 0; x < allSubs.Count; x++)
{
if (e.IDfromCategories == allSubs[x].iDfromSubCategories)
e.isChecked = true;
}
branch.Add(e);
}
So I am using a nested loop. But since I have to do this multiple times, it takes far too long.
I also thought about turning all values from SubCategories into a simple string array and use the Contains function, to see if the current object.IDfromCategories contains the object on the array. This would mean I would NOT use a for loop. But interenally, I believe, the system is still using a loop and therefore there would be no performance benefit.
What would be the best way of checking each object if it contains a value from the other list?
You should use some kind of lookup table. Probably either HashSet or Dictionary. The former only allows checking if a key exists in the set, while the later allows you to also find the object the key belongs to.
To check all the UserInsideCategories that shares an id with a SubCategories you could write:
var dict = subCategoriesList.ToDictionary(s => s.subCategoryID, s => s);
var matches = userInsideCategoriesList.Where(l => dict.ContainsKey(l.iDfromSubCategories));
if you want matching pairs you could write:
foreach (var user in userInsideCategoriesList)
{
if (dict.TryGetValue(user.iDfromSubCategories, out var subCategory))
{
// Handle matched pairs
}
}
This assumes that the ID is unique in respective list. If you have duplicates you would need something like a multi-value dictionary. There are no multi-value dictionary built in, but I would expect there are some implementations if you search around a bit.

Compare one value to next value in a sorted dictionary

I have a sorted dictionary having names as key and marks as value.
Dictionary<string,int> diM = new Dictionary<string,int>();
Another dictionary to store time taken by respective student.
Dictionary<string,int> diT = new Dictionary<string,int>();
Now if the marks of the two students are same then ranking based on time taken.
var marks = from pair in diM
orderby pair.Value descending
select pair;
int j=0;
foreach (KeyValuePair<string, int> pair in marks)
{
j++;
Console.WriteLine("{0} {1}",j, pair.Key);
}
Now if one student marks are equal with next student marks (as sorted Dictionary) then student with less time should be output.
First I'd recommend not using dictionaries for this task. Create a class with properties of name, mark and time. Something like:
public class TestResult
{
public string Name { get; set; }
public int Grade { get; set; }
public TimeSpan Time { get; set; }
}
Then hold a list of that type. Whenever you have two separate collections which you somehow need to keep in sync - suspect that there might be a problem in the design.
As for the actual problem, use Linq to join the two dictionaries by the key. Once you did that you can order the results by the mark and then by the time:
var result = from mark in diM
join time in diT on mark.Key equals time.Key
orderby mark.Value descending, time.Value
select new { Name = mark.Key, Grade = mark.Value, Time = time.Value };

when i loop though tuple list it show me index out of range error

my kitchen list format are this List<Tuple<string,string,string>> .I can filled it on kitchen class method and i can display it on datagridview by calling that method by kitchen class object when i apply foreach loop on it it show me index out of range exception
kitchen = new Kitchen();
List<Tuple<string, string, string>> kitchenList = kitchen.getKitchens();
dgv_kitchen.Rows.Clear();
if (kitchenList.Count > 0)
{
for (int i = 0; i < kitchenList.Count; i++)
{
dgv_kitchen.Rows[i].Cells["id"].Value = kitchenList[i].Item1.ToString();
dgv_kitchen.Rows[i].Cells["kitchen_name"].Value = kitchenList[i].Item2.ToString();
dgv_kitchen.Rows[i].Cells["categories"].Value = kitchenList[i].Item3.ToString();
}
}
You're clearing the list of rows - but then trying to access those non-existent rows by index. Contrary to your title, it's not "looping through a tuple list" that's causing the problem - it's what you're doing with the results.
Instead, you should be creating new rows and adding them. Note that this is easier with a foreach loop than a for loop, and you don't need to check the count first either way:
kitchen = new Kitchen();
List<Tuple<string, string, string>> kitchenList = kitchen.getKitchens();
dgv_kitchen.Rows.Clear();
foreach (var tuple in kitchenList)
{
dgv_kitchen.Rows.Add(new object[] { tuple.Item1, tuple.Item2, tuple.Item3 };
}
That's assuming the DataGridView displays just id/kitchen_name/categories in that order.
A better solution would be to avoid setting the cell values directly, and instead bind the DataGridView to a data source. I'd also avoid the tuples. So you might have:
public class Kitchen
{
public string Id { get; }
public string Name { get; }
public string Categories { get; }
public Kitchen(string id, string name, string categories)
{
Id = id;
Name = name;
Categories categories;
}
}
You'd then change your current getKitchens method to something like:
public IReadOnlyList<Kitchen> GetKitchens()
Then you can replace all of the existing code with:
dgv_kitchens.DataSource = GetKitchens();

How to iterate over this particular type of Dictionary<int, Result>?

I have a bunch of results from the Database that I keep in a Dictionary<int, Result>().
The Result class I have is:
public int Id { get; set; }
public string something { get; set; }
public string somethingtwo { get; set; }
public string somethingthree { get; set; }
public DateTime Posted { get; set; }
public string Location { get; set; }
public bool somethingfour { get; set; }
So, the Dictionary<int, Result> has many Results inside and I'd like to iterate over them. How an I do this? I've tried a few ways, but even I knew they wouldn't work.
I would like to do something like this:
foreach(var result in resultDict)
{
mynewstring = result.Location;
mynewstringtwo = result.Posted;
// etc etc.
}
foreach(var kvp in resultsDict) {
//Do somethign with kvp
UseResult(kvp.Value); //kvp.Value is a Result object
UseKey(kvp.Key); //kvp.Key is the integer key you access it with
}
In the above code kvp is a KeyValuePair<int, Result>. You can access the Key and Value properties to get the integer key of the Dictionary and the Result value associated with that Key. I'll leave it as an excercise/guessing game for you to figure out which property is which! ;-)
As #Wiktor mentions, you can also access the dictionary's Values and Keys collections to do the same thing, but retrieve a sequence of int or Value properties instead.
Alternatives using the other collections:
foreach(var val in resultsDict.Values) {
// The key is not accessible immediately,
// you have to examine the value to figure out the key
UseResult(val); //val is a value.
}
foreach(var key in resultsDict.Keys) {
//The value isn't directly accessible, but you can look it up.
UseResult(resultsDict[key]);
UseKey(key);
}
Dcitionary has a ValueCollection called Values, so the code would be:
foreach (Result r in dict.Values)
{
mynewstring = result.Location;
mynewstringtwo = result.Posted;
}
var dictionary = ...;
foreach ( var result in dictionary.Values )
{
...
}
Is that what you need?
You can use the Values property to iterate over the values of a Dictionary (see also the MSDN page).
Code example:
// Your dictionary
var myResultDictionary = new Dictionary<int, Result>();
foreach (var item in myResultDictionary.Values)
{
// "item" holds a Result object
// Do something with item
}
You can also regularly loop over your Dictionary, however item will be a KeyValuePair (MSDN page) object. You can access the value with the Value property on the variable item.
Code example:
// Your dictionary
var myResultDictionary = new Dictionary<int, Result>();
foreach (var item in myResultDictionary)
{
// "item" holds a KeyValuePair<int, Result> object
// You can access the value (a Result object) by calling "item.Value"
// Do something with item
}
You can iterate over Dictionary.Values, which would be like any other IEnumerable<Result>
Or, you can iterate over Dictionary, which is an IEnumerable<KeyValuePair<int, Result>>
foreach (KeyValuePair<int,Result> item in dictionary)
{
//do stuff
}
foreach(KeyValuePair<int,result> keyValue in yourDictionary)
{
Debug.WriteLine(keyValue.Value);
//or
Debug.WriteLine(keyValue.Key);
}
or the same thing, but using var:
foreach(var keyValue in yourDictionary)
{
Debug.WriteLine(keyValue.Value);
//or
Debug.WriteLine(keyValue.Key);
}
^^ same thing, but var dynamically figures out its own type
or you can do this, if you just need the result:
foreach(var result in yourDictionary.Values)
{
Debug.WriteLine(result);
}
Use a foreach on the Dictionary:
foreach (var keyValue in dictionary)
{
//Use key value here
}

Categories