【问题标题】:How to Compare multi dimentional string array?如何比较多维字符串数组?
【发布时间】:2014-01-20 04:51:49
【问题描述】:

我想比较 2 个字段。即机器和通行证。

我想根据机器的值连接“颜色”并通过。

--------------|------------------|------------
 Color1       | Machine 1        | Pass 1 
--------------|------------------|------------
 Color2       | Machine 2        | Pass 1 
--------------|------------------|------------
 Color3       | Machine 1        | Pass 1 
--------------|------------------|------------
 Color4       | Machine 1        | Pass 2 
--------------|------------------|------------
 Color5       | Machine 2        | Pass 1 
--------------|------------------|------------
 Color6       | Machine 2        | Pass 2 
--------------|------------------|------------

我想要的结果如下。

  1. 机器 1 和通道 1 的颜色 1/颜色 3
  2. 机器 2 和通道 2 的颜色 2/颜色 5
  3. 机器 1 和通道 2 的颜色 4
  4. 机器 2 和 Pass2 的颜色 6

我不知道如何得到这个结果。尝试了很多方法,但没有得到我想要的方式

【问题讨论】:

  • 提供数组的实际声明。让回答更容易。

标签: c# arrays string multidimensional-array


【解决方案1】:

这是你的答案,

private void button1_Click(object sender, EventArgs e)
{
    var ary = new[]
    {
        "Color1       | Machine 1     | Pass 1 ",
        "Color2       | Machine 2     | Pass 1 ",
        "Color3       | Machine 1     | Pass 1 ",
        "Color4       | Machine 1     | Pass 2 ",
        "Color5       | Machine 2     | Pass 1 ",
        "Color6       | Machine 2     | Pass 2 "
    };

    var seprated = from x in ary.Select(x => x.Split('|'))
                    select new
                    {
                        key = x[1].Trim() + "&" + x[2].Trim(),
                        value = x[0]
                    };

    var sb = new StringBuilder();
    foreach (var key in seprated.Select(x => x.key).Distinct())
    {
        var colors = seprated.Where(x => x.key == key).Select(x => x.value.Trim()).ToArray();
        sb.AppendLine(string.Format("{0} for {1}", string.Join("/", colors), key));
    }

    textBox1.Text = sb.ToString();
}

sb.toString() 有结果:

机器 1&Pass 1 的颜色 1/颜色 3

机器 2&Pass 1 的 Color2/Color5

机器 1&Pass 2 的 Color4

机器 2&Pass 2 的 Color6

【讨论】:

  • 我喜欢这个答案,因为它正在使用机器并作为唯一键传递(与颜色#形成某种关系)。
【解决方案2】:
        var multidimensionalArray = new[,]
            {
                {"Color1", "Machine 1", "Pass 1"},
                {"Color2", "Machine 2", "Pass 1"},
                {"Color3", "Machine 1", "Pass 1"},
                {"Color4", "Machine 1", "Pass 2"},
                {"Color5", "Machine 2", "Pass 1"},
                {"Color6", "Machine 2", "Pass 2"}
            };

        var tuple = new List<Tuple<string, string, string>>();
        for (var i = 0; i < multidimensionalArray.Length/3-1; i++)
        {
            tuple.Add(new Tuple<string, string, string>(multidimensionalArray[i, 0], multidimensionalArray[i, 1], multidimensionalArray[i, 2]));
        }

        foreach (var el in tuple.GroupBy(x => String.Format("{0} & {1}", x.Item2, x.Item3), y => y.Item1))
        {
            Console.WriteLine(String.Join("/", el) + " for " + el.Key);
        }

【讨论】:

  • OP 说输入是一个多维字符串数组,而不是元组列表。此外,将字符串连接在一起是对两个值进行分组的一种非常容易出错的方式。如果机器值为“12”且通过“3”,它将与机器值为“1”且通过“23”的行分组。使用“&”分隔符会有所帮助,但如果分隔符存在于基础数据中的每个值之间,那么它仍然会失败。
  • 我怀疑,OP 从 SQL 中获取数据,只想存储字符串并寻找概念方式。
  • 我不明白为什么数据是否来自 SQL 很重要;连接字符串以创建密钥仍然不是合适的 concept 。它可能导致碰撞。适当的概念是创建一个新对象来表示多个值,这些值可以具有适当的“相等”定义。
  • 当然。但是 OP 想要存储多维字符串数组,而不是对象。
  • 如何组织数据存储:为通行证和机器制作外键。使用 EntityFramework 连接到数据库。另一种创建 SQL 视图的方法,它对分组数据进行透视。
【解决方案3】:

您没有提供类定义,所以我假设它是以下内容

class PaintMachineInfo
{
    public string ColorName {get; set;}
    public string MachineName {get; set;}
    public string Pass {get; set;}
}

您可以使用.ToLookup( 轻松获得您想要的结果,它允许您做的是提供一个键,它会为您提供与该键匹配的 IEnumerable 结果。

我喜欢为查找键使用自定义类而不是 Tuple,因为它使您正在查看的内容更加明显,而且创建类的代码也不多。

private static void Main(string[] args)
{
    List<PaintMachineInfo> info = GenerateInfo();

    var filteredResults = info.ToLookup(line => new PaintMachineLookup(line.MachineName, line.Pass), line => line.ColorName);

    //Contains a IEnumerable<string> containing the elements "Color1" and "Color3"
    var result1 = filteredResults[new PaintMachineLookup("Machine 1", "Pass 1")];

}

private static List<PaintMachineInfo> GenerateInfo()
{
    //...
}

class PaintMachineInfo
{
    public string ColorName { get; set; }
    public string MachineName { get; set; }
    public string Pass { get; set; }
}

internal class PaintMachineLookup
{
    public PaintMachineLookup(string machineName, string pass)
    {
        MachineName = machineName;
        Pass = pass;
    }
    public string MachineName { get; private set; }
    public string Pass { get; private set; }

    public override int GetHashCode()
    {
        unchecked
        {
            int x = 27;
            x = x * 11 + MachineName.GetHashCode();
            x = x * 11 + Pass.GetHashCode();
            return x;
        }
    }

    public override bool Equals(object obj)
    {
        var other = obj as PaintMachineLookup;
        if (other == null)
            return false;

        return MachineName.Equals(other.MachineName) && Pass.Equals(other.Pass);
    }
}

【讨论】:

  • 这个答案看起来最有希望,因为我猜他还没有三个值的数组(集合),以便将它们分开,以便将它们放在一起再次...
  • @WonkotheSane 在这种情况下,将ToLookup 从使用.ToLookup(line =&gt; new PaintMachineLookup(line.MachineName, line.Pass), line =&gt; line.ColorName) 更改为.ToLookup(line =&gt; new PaintMachineLookup(line[1], line[2]), line =&gt; line[0]) 是微不足道的(假设infostring[][]
  • @ScottChamberlain 但他说他有一个多维数组。 string[][] 不是多维数组。在多维数组上执行转换并不是那么简单。
  • @Servy 公平点。我不确定我会为string[,] 做些什么,我不经常与他们合作。
  • @ScottChamberlain 查看我的答案以了解一种可能性。虽然你可以使用一些 LINQ 来做到这一点,但我发现不这样做更容易。
【解决方案4】:

首先,从概念上讲,这里真正拥有的是一个复杂对象的单一维度,它同时具有颜色、机器和传递值。将其存储在二维数组中并不是一个好主意。更好的表示是某个自定义类型的List,所以让我们先进行转换。

首先,我们将定义一个自定义类型来表示输入数据:

public class MachinePass//TODO consider renaming
{
    public string Color { get; set; }
    public string Machine { get; set; }
    public string Pass { get; set; }
}

然后我们将解析我们的输入并将其放入适当的结构中:

var list = new List<MachinePass>();
for (int i = 0; i < data.GetLength(0); i++)
{
    var next = new MachinePass();
    next.Color = data[i, 0];
    next.Machine = data[i, 1];
    next.Pass = data[i, 2];
    list.Add(next);
}

现在我们有了这个,我们可以应用我们的业务逻辑。在这种情况下,您想要做的是按机器和通过对这些行进行分组,然后获取这些组的颜色。 GroupBy LINQ 运算符让这变得超级简单:

var query = list.GroupBy(row => new { row.Machine, row.Pass }
    , row => row.Color);

然后我们可以按照定义的格式打印出这个查询的结果:

foreach(var group in query)
    Console.WriteLine("{0} for {1} & {2}",
        string.Join("/", group),
        group.Key.Machine,
        group.Key.Pass);

【讨论】:

    猜你喜欢
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多