我正在编写一个C#程序,在这个程序中,我需要使用元数据填充一个基于查找表和一组字符串数组的数组。我的查找表如下所示(带有键的表:发射器,值:接收器数组):
{
LED1: ["px1","px2","px3"],
LED2: ["px4","px5","px6"]
}我的元数组看起来像这样(它是动态的(只是一个例子),并作为来自DB查询的响应):
var transmitters = new string[] { "LED1", "LED2" };
var receivers = new string[] { "px1", "px2", "px3", "px4", "px5", "px6" };我的要求是:
{
LED1: ["px1", "px2", "px3"],
LED2: ["px5", "px8"]
}发射机和接收器
var transmitters = new string[] { "led1", "led2" };
var receivers = new string[] { "px1", "px2", "px3", "px4", "px5", "px6" };结果应该是一份清单如下:
led1-yellow
px1-yellow
px2-yellow
px3-yellow
led2-yellow
px5-yellow
px4-red
px6-red.我编写的代码可以:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var transmitters = new string[] { "led1", "led2", "led3" };
var receivers = new string[] { "px1", "px2", "px3", "px4", "px5", "px6" };
var lookup = new Dictionary<string, string[]>() {
{ "led1", new string[] { "px1", "px2", "px3" } },
{ "led2", new string[] { "px5", "px8"} }
};
var blocks = new List<Block>();
var blocksTracker = new List<string>();
foreach (var transmitter in transmitters)
{
if (lookup.ContainsKey(transmitter))
{
var receiverLookup = lookup[transmitter];
var intersection = receivers.Intersect(receiverLookup).ToArray();
if (intersection.Length > 0)
{
blocks.Add(new Block() { Id = transmitter, status = "yellow"});
blocksTracker.Add(transmitter);
foreach (var receiver in intersection)
{
blocks.Add(new Block(){Id = receiver, status = "yellow"});
blocksTracker.Add(receiver);
}
} else
{
blocks.Add(new Block(){Id = transmitter, status = "red"});
blocksTracker.Add(transmitter);
}
}
}
var ungrouped = receivers.Except(blocksTracker).ToArray();
foreach (var receiver in ungrouped)
{
blocks.Add(new Block(){Id = receiver, status = "red"});
blocksTracker.Add(receiver);
}
foreach (var i in blocks)
{
Console.WriteLine(i.Id + "-"+i.status);
}
}
public class Block
{
public string Id { get; set; }
public string status { get; set; }
}
}我是C#的新手,我想知道是否有更好的方法来做到这一点。您可以看到工作Fiddle 这里。
发布于 2019-04-26 11:52:51
if (lookup.ContainsKey(transmitter)) { var receiverLookup = lookup[transmitter];
这将搜索两次KeyValuePair。有一种更有效的方法:
if (lookup.TryGetValue(transmitter, out var receiverLookup))var ungrouped = receivers.Except(blocksTracker).ToArray(); foreach (var receiver in ungrouped) { blocks.Add(new Block(){Id = receiver, status = "red"}); blocksTracker.Add(receiver); }
这里的ToArray()是不必要的:枚举可以保留为惰性枚举,因为惟一的用途是对它进行一次迭代。
var intersection = receivers.Intersect(receiverLookup).ToArray(); if (intersection.Length > 0) { blocks.Add(new Block() { Id = transmitter, status = "yellow"}); blocksTracker.Add(transmitter); foreach (var receiver in intersection) { blocks.Add(new Block(){Id = receiver, status = "yellow"}); blocksTracker.Add(receiver); } } else { blocks.Add(new Block(){Id = transmitter, status = "red"}); blocksTracker.Add(transmitter); }
这似乎相当复杂。我认为整件事可以简化:
var transmittersPaired = new HashSet<string>();
var receiversPaired = new HashSet<string>();
foreach (var transmitter in transmitters)
{
if (lookup.TryGetValue(transmitter, out var receiverLookup) && receiverLookup.Any())
{
transmittersPaired.Add(transmitter);
foreach (var receiver in receiverLookup)
{
receiversSeen.Add(receiver);
}
}
}
var blocks = new List<Block>();
foreach (var transmitter in transmitters)
{
blocks.Add(new Block { Id = transmitter, status = transmittersPaired.Contains(transmitter) ? "yellow" : "red" });
}
foreach (var receiver in receivers)
{
blocks.Add(new Block { Id = receiver, status = receiversPaired.Contains(receiver) ? "yellow" : "red" });
}还有一些重复的代码,这些代码可以通过两种方式中的一种进行简化。如果能够保证发射机和接收器永远不会共享If,那么transmittersPaired和receiversPaired就可以合并成一个集合,最后的foreach循环可以在transmitters.Concat(receivers)上合并成一个循环。或者,可以将一个方法考虑在内。
https://codereview.stackexchange.com/questions/219172
复制相似问题