【问题标题】:How to C# linq GroupBy multiple arrays with array values如何 C# linq GroupBy 具有数组值的多个数组
【发布时间】:2015-04-29 07:22:26
【问题描述】:

我有一个对象数组“通道”,每个对象都有属性

string axis

//times and values correspond to each other. Their lengths will always be the same. times[0] value is values[0], etc...   
float[] times
float[] values

假设通道数组中有 3 个通道,它们的 float[] "times" 值为...

channel[0].times = 1, 2, 3, 4, 5, 6
channel[1].times = 0, 2, 2.5, 3, 5, 6
channel[2].times = 1, 2.5, 3, 4, 5.5, 6

MiniChannel 对象具有属性

string axis
float value;

我正在寻找的结果是这样的......

Dictionary<float, MiniChannel[]> MatchingTimes;
//float corresponds to the times value 

MatchingTimes[0] 包含...

new MiniChannel0
MiniChannel.axis = channel[1].axis
MiniChannel.value= channel[1].values[0]

MatchingTimes[1] 包含...

new MiniChannel0
MiniChannel.axis = channel[0].axis
MiniChannel.value= channel[0].values[0]

new MiniChannel1
MiniChannel.axis = channel[2].axis
MiniChannel.value = channel[2].values[0]

.....

MatchingTimes[5.5] 包含...

new MiniChannel0
MiniChannel.axis = channel[2].axis
MiniChannel.value= channel[2].values[4]

等...等...每个时间值。

所以我试图将所有通道同时分组,并获取它们在该时间的值以及它们的字符串轴。

我四处寻找有关 groupby linq 方法的答案,但我只看到人们处理单个数组或具有多个元素的数组,但每个元素仍然只有一项。

感谢任何帮助。

【问题讨论】:

    标签: c# arrays linq


    【解决方案1】:

    试试这个:

    IDictionary<float, MiniChannel[]> matchingTimes = channel
        .SelectMany(c => c.times.Select((t, i) => new KeyValuePair<float, MiniChannel>(t, new MiniChannel {axis = c.axis, value = c.values[i]})))
        .GroupBy(t => t.Key)
        .ToDictionary(t => t.Key, t => t.Select(c => c.Value).ToArray());
    

    【讨论】:

    • 我没有尝试过这个,因为它使用了元组,我使用的 C# 版本不支持(统一引擎的脚本)。不过,玉米片的答案似乎有效。
    • 您可以将Tuple 替换为任何类(例如KeyValuePair 也适用)。我已经更新了我的答案。
    • kk,我认为这个答案一切都很好。以后有问题再回帖。
    【解决方案2】:

    据我所知:(顺便说一句......你没有分配时间数组......所以我用times而不是values

    你的价值观的基本设置:

    public class MiniChannel
    {
        public string Axis { get; set; }
        public float Value { get; set; }
    }
    
    public class Channel
    {
        public string Axis { get; set; }
        public float[] Times { get; set; }
        public float[] Values { get; set; }
    }
    

    和查询:

    Channel[] channels = new Channel[3];
    
    channels[0] = new Channel
    {
        Axis = "channel1",
        Times = new[] { 1f, 2f, 3f, 4f, 5f, 6f }
    };
    
    channels[1] = new Channel
    {
        Axis = "channel1",
        Times = new[] { 0f, 2f, 2.5f, 3f, 5f, 6f }
    };
    
    channels[2] = new Channel
    {
        Axis = "channel1",
        Times = new[] { 1f, 2.5f, 3f, 4f, 5.5f, 6f }
    };
    
    MiniChannel miniChannel0 = new MiniChannel {Axis = channels[0].Axis, Value = channels[0].Times[0]};
    MiniChannel miniChannel1 = new MiniChannel {Axis = channels[1].Axis, Value = channels[1].Times[0]};
    MiniChannel miniChannel2 = new MiniChannel {Axis = channels[2].Axis, Value = channels[2].Times[0]};
    
    List<MiniChannel> list = new List<MiniChannel>
    {
        miniChannel0, miniChannel1, miniChannel2
    };
    
    var result = from minichannel in list
        group minichannel by minichannel.Value
        into g
        select new {Value = g.Key, Items = g};
    
    Dictionary<float, MiniChannel[]> dict = result.ToDictionary(key => key.Value, value => value.Items.Select(x => x).ToArray());
    

    【讨论】:

    • 我认为我在问题中写的一些内容可能会让您感到困惑(我并没有用我的例子来说明)。检查 Krzysztof 答案以查看我正在寻找的示例。
    【解决方案3】:

    如果我理解正确......这是一个可能的解决方案

    已编辑:

    Dictionary<float, MiniChannel[]> MatchingTimes = channel
              .SelectMany(c => c.times)
              .Distinct()
              .ToDictionary(k => k, v => channel
                            .Where(c => c.times.Contains(v))
                            .Select(c => new MiniChannel {
                                axis = c.axis,
                                value = c.values[Array.IndexOf(c.times, v)]
                            })
              .ToArray());
    

    【讨论】:

    • 我还没有完全测试,但这似乎正是我想要的。谢谢!如果我遇到问题,我会将其取消标记为答案。
    • 在你的结果中 value 总是等于 times (或字典键),而它应该是 values 数组元素
    • 是的,我刚刚注意到这一点,并且正准备取消将其标记为答案。我没有注意到这只是时间回来。该值必须是 values 数组中的实际值。
    • Ops...我编辑了答案,我认为它现在可以工作了。
    【解决方案4】:

    使用选择的答案,我能够做到这一点......

    using System;
    using System.Linq;
    using System.Collections.Generic;
    
    public static partial class ExtHelper
    {
        public static Dictionary<T, W[]> GroupEqualsInObjects<T, U, W>(this U[] items, Func<U, T[]> funcVariables, Func<U, int, W> funcValues)
        {
            Dictionary<T, W[]> MatchingItems = items
            .SelectMany(c => funcVariables(c)
            .Select((t, i) => new {key = t, item = funcValues(c, i)})
            .ToDictionary(x => x.key, y => y.item))
            .GroupBy(t => t.Key)
            .ToDictionary(t => t.Key, t => t.Select(c => c.Value).ToArray());
    
            return MatchingItems;
        }
    }
    

    可以这样使用...

    Dictionary<float, MiniChannel[]> MatchingTimes = channels.GroupEqualsInObjects<float, ChannelObject, MiniChannelObject>(c => c.times, (c, i) => new MiniChannel{axis = c.axis, value = c.values[i]});
    

    您可能不需要特别声明泛型 float、ChannelObject 和 MiniChannelObject,因为当我删除它们时它没有显示红线,但由于我使用的是统一游戏引擎,它在较低版本的 c# 上运行,它给了我错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2020-01-09
      • 2018-03-07
      • 1970-01-01
      相关资源
      最近更新 更多