There are devices that communicate between each other. Already existing in the Legacy codebase is a list of one-to-many mappings between the devices. I have written a function in my backend that processes this list. Each mapping is in the form of a custom object that stores the source object and the multiple destinations that the source is mapped to.
In the front-end, I have a list of devices as checkboxes. When I select a device, I need to find out for each device, all the other devices that it is related to, both, when acting as a sender, or and as a receiver. Then I need to check those boxes as well.
My approach so far has been to iterate over each Key-Value Pair in the custom mapping list, find the source, identify the destinations in the mapping, add this to a source-destination collection.
Then, iterate over this mapping list again. But this time, because the source-destination mapping is one-to-many, I find that getting a destination, adding it to a list and backtracking towards the entire list to find out sources can be quite inefficient once the sizes get large. But I am unable to think of a more efficient way to do the same.
The current code works. But freezes the UI for a few seconds when it runs, but I think the approach and/or the usage of Data Structures can be optimized. Readability and semantic correctness is what I am looking for.
public static List<Dictionary<string, List<string>>> GetDependentDeviceMasterSet(Dictionary<CustomDeviceStruct, List<dataTag>> externalMappingList)
{
var sourceDestinationMappings = new Dictionary<string, List<string>>();
var destinationSourceMappings = new Dictionary<string, List<string>>();
var mappings = new List<Dictionary<string, List<string>>>();
foreach (var externalMapping in externalMappingList)
{
var sourceName = externalMapping.Key.deviceName;
if (sourceDestinationMappings.ContainsKey(sourceName))
{
foreach (var data in externalMapping.Value)
{
var destinationName = data.deviceName;
if((sourceDestinationMappings[sourceName]).Contains(destinationName) == false)
{
(sourceDestinationMappings[sourceName]).Add(destinationName);
if (destinationSourceMappings.ContainsKey(destinationName))
{
foreach (var includedSourceName in destinationSourceMappings[destinationName])
{
if (destinationSourceMappings[destinationName].Contains(includedSourceName) == false)
{
destinationSourceMappings[destinationName].Add(includedSourceName);
}
}
}
}
}
}
else
{
var destinations = new List<string>();
foreach (var data in externalMapping.Value)
{
var destinationName = data.deviceName;
destinations.Add(destinationName);
if (destinationSourceMappings.ContainsKey(destinationName))
{
if (destinationSourceMappings[destinationName].Contains(sourceName) == false)
{
destinationSourceMappings[destinationName].Add(sourceName);
}
}
else
{
var sources = new List<string>();
sources.Add(sourceName);
destinationSourceMappings.Add(destinationName, sources);
}
}
sourceDestinationMappings.Add(sourceName, destinations);
}
}
mappings.Add(sourceDestinationMappings);
mappings.Add(destinationSourceMappings);
return mappings;
}
And in the front-end, I process it like so :
private void FillAllNodesThatAreRelatedTo(TreeNode selectedDeviceNode)
{
foreach(TreeNode childNode in selectedDeviceNode.Parent.Nodes)
{
if (childNode.Text == selectedDeviceNode.Text)
{
continue;
}
if (this.dependentDeviceMasterSet[0].ContainsKey(selectedDeviceNode.Text))
{
var sourceDestinationMapping = this.dependentDeviceMasterSet[0][selectedDeviceNode.Text];
if (sourceDestinationMapping.Contains(childNode.Text))
{
childNode.Checked = true;
continue;
}
else
{
childNode.Checked = false;
continue;
}
}
if (this.dependentDeviceMasterSet[1].ContainsKey(selectedDeviceNode.Text))
{
var destinationSourceMapping = this.dependentDeviceMasterSet[1][selectedDeviceNode.Text];
if (destinationSourceMapping.Contains(childNode.Text))
{
childNode.Checked = true;
continue;
}
else
{
childNode.Checked = false;
continue;
}
}
if ((this.dependentDeviceMasterSet[0].ContainsKey(selectedDeviceNode.Text) == false) &&
(this.dependentDeviceMasterSet[1].ContainsKey(selectedDeviceNode.Text) == false))
{
childNode.Checked = false;
continue;
}
}
}
For the first line of code, using LINQ what I have tried so far to simplify it is:
var mappingsThatContainSource = from mapping in externalMappingList
where sourceDestinationMappings.ContainsKey(mapping.Key.deviceName)
select mapping;
But I am unsure if I am on the right track. Known issues:
- Too much nesting. Hence, a want to try LINQ.
- Inefficient use of Data Structures