【问题标题】:Get index array of value changes or first distinct values from array of Objects从对象数组中获取值更改的索引数组或第一个不同的值
【发布时间】:2021-02-17 02:52:13
【问题描述】:

我有一个包含 3 个双精度对象的排序数组,我们称它们为 x、y 和 z。我需要为每个转换点创建一个索引数组,例如:

index   x   y   z
------------------
  0  |  3 | 2 | 1
  1  |  4 | 3 | 1
  2  |  3 | 1 | 1
  3  |  1 | 3 | 2
  4  |  3 | 1 | 2
  5  |  1 | 3 | 3
  6  |  1 | 3 | 3

应该给我数组 {3,5} 因为那是 z 变化的点,我试过了 var ans = myObjectArr.Select(a => a.z).Distinct().ToList();但这只是给了我一个值本身的列表,而不是它们在对象数组中的索引。该数组非常大,我想避免谨慎地遍历它。我觉得我只是错过了一些愚蠢的东西,任何帮助将不胜感激。生成列表或数组都是可以接受的。

编辑:我的印象是使用 Linq 比迭代更快,在阅读 cmets 后我发现情况并非如此,因此 Charlieface 的答案是解决我的问题的最佳答案。

【问题讨论】:

  • "避免谨慎地迭代我的方式" - 是的,无论如何,您使用的任何解决方案都需要这样做。只需使用 for 循环,并考虑可以减少多少可打印字符,或者以后是否可以将其放在一行中
  • 很多可能的方法。例如,参见副本。如果在进行了一些实际研究、查看了您可用的信息并真正尝试实施解决方案后,您遇到了一些您无法解决的特定问题,请随时发布另一个问题。如果您这样做,请确保在其中包含正确的minimal reproducible example,并详细说明代码的作用、与您想要的有何不同以及您需要帮助的具体 .
  • 如果您也使用 MoreLinq,var ans = myObjectArr.Select((a, index) => new {z = a.z, index = index}).DistinctBy(z => z.z).ToList(); 可能也有效。
  • @AlexeiLevenkov:我不知道他们将如何避免 O(N),至少在最坏的情况下是这样。他们在帖子中没有说任何关于采访的内容。只是他们“希望避免迭代”。我希望我的所有代码都由计算机为我编写,而不需要我自己做任何努力。某人“想要”某事并不意味着它是可能的,不符合的答案也不是他们问题的答案。
  • @user3599976 我读这个问题的方式看起来像是面试一,对此感到抱歉。 LINQ 解决方案确实可以比给定问题的错误解决方案更快(例如 O(n^2) 集合的交集),但永远不会比最佳编码的解决方案更快(因为 LINQ 只是代码,只是更通用一点,因此更慢,加上它无法处理信息不直接可用的情况 - 即排序序列没有优化)。在您的情况下,由于无法对 2d/3d 值进行排序,因此您的排序根本没有帮助 - 所以线性搜索很好......

标签: c# arrays ienumerable


【解决方案1】:
var lastZ = myObjectArr[0].z;
var zIndexes = new List<int>();
for(var i = 1; i < myObjectArr.Length; i++)
{
    if(myObjectArr[i] != lastZ)
    {
        lastZ = myObjectArr[i];
        zIndexes.Add(i);
    }
}
// or you can use obscure Linq code if it makes you feel better
var zIndexes = myObjectArr
    .Select((o, i) => (o, i))
    .Skip(1)
    .Aggregate(
        new List<int>(),
        (list, tuple) => {
            if(tuple.o.z != lastZ)
            {
                lastZ = tuple.o.z;
                list.Add(tuple.i);
            }
            return list;
        } );

【讨论】:

  • 如何“避免重复我的方式”?
  • 您必须以某种方式进行迭代。甚至 Linq 也会迭代
  • OPs(可能是面试)问题指出数组已排序(可能按 Z 列)。因此,您需要展示在排序数组中找到边界的方法,或者解释它并不重要(两个很好的答案,一个可能需要解释为什么它并不重要)
  • 我可能会使用它,我发现 Linq 解决方案通常比使用 for 循环迭代它花费的时间更少,但通过阅读其他答案,似乎没有一个简单的解决方案。对 Alexi 的评论,这不是面试问题,而是我遇到的现实问题。
  • @user3599976 由于额外的实例化和间接性,Linq 通常需要 更长for 数组上的循环几乎总是更快
猜你喜欢
  • 2015-04-24
  • 1970-01-01
  • 2023-01-23
  • 2023-03-20
  • 1970-01-01
  • 2020-11-27
  • 2023-03-24
  • 2018-03-28
  • 2018-11-25
相关资源
最近更新 更多