【问题标题】:Going through a list to get similar elements and indexes遍历列表以获取相似的元素和索引
【发布时间】:2014-01-27 10:55:35
【问题描述】:

我有一个 List myList = new List() { 8 ,5 ,3 ,3 ,3, 3, 3 ,3 ,4 ,5 ,3 , 8 };

假设我选择了列表中的第 5 个元素,即 3。

我想找到给定元素的相似值的开始和结束索引,只要它是相似的

所以,我需要前 3 个(在本例中为 2)和最后 3 个(在本例中为 7)的索引。

为此,我决定使用 while 循环转到列表的开头,并使用另一个 while 循环转到列表的末尾。

但这感觉像是实现预期结果的昂贵/缓慢的方式。

您知道更快/更好的方法吗?

谢谢!

【问题讨论】:

  • 如果您选择第二个元素 (5),正确的结果应该是什么?
  • 对,应该是1,1
  • 如果感觉很慢,那是因为它不能假设您的列表没有任何内容可以实现更智能的行为。该列表是否有一些可以提供帮助的有保证的财产?如果没有,没有比这更好的了。
  • 您是在挑选指数还是价值?因为在上面的列表中,3 也排在第 10 位。
  • @Naveen 我正在选择价值。第10位的3不应该考虑

标签: c# performance c#-4.0 logic


【解决方案1】:

这是一个可能但并不优雅的解决方案:

List<int> myList = new List<int> { 8, 5, 3, 3, 3, 3, 3, 3, 4, 5, 3, 8 };

        var index = 5;

        var element = myList.ElementAt(index);
        int firstIndex=index, lastIndex=index;

        int i, j;
        bool control1 = true, control2 = true;
        for (i = index, j = index; ; i--, j++)
        {
            if (control1 && i >= 0 && myList[i] == element)
            {
                firstIndex = i;
            }
            else
            {
                control1 = false;
            }

            if (control2 && j < myList.Count && myList[j] == element)
            {
                lastIndex = j;
            }
            else
            {
                control2 = false;
            }

            if (!control1 && !control2) break;
            if (i < 0 && j >= myList.Count) break;
        }

        Console.WriteLine(firstIndex);
        Console.WriteLine(lastIndex);

输出:

// index = 5

   firstIndex = 2, lastIndex = 7

// index = 1

    firstIndex = 1, lastIndex = 1

// index = 8

    firstIndex = 8, lastIndex = 8

【讨论】:

  • 谢谢,我试试这个
【解决方案2】:

假设您正在谈论大型列表,那么执行您的方法的两个线程可能会很有用。你需要一个像

这样的函数
int getSimilarIndex(IReadOnlyList<int> list, int startIndex, bool forward) {
    int index = startIndex;
    int startElement = list[startIndex];
    while (forward ? (index < list.Count) : (index >= 0) ) {    
        if (!isSimilar(list[index], startElemen))
            break;
        if (forward)
            ++index;
        else
            ++index;
    }
    return index;
}

返回相似条目的第一个/最后一个索引。现在您可以将该函数的两个版本分配给 ThreadPool-Threads:

ThreadPool.QueueUserWorkItem( (WaitCallback) delegate {
    this.minSimilarIndex = getSimilarIndex(list, startIndex, false);
    });
ThreadPool.QueueUserWorkItem( (WaitCallback) delegate {
    this.maxSimilarIndex = getSimilarIndex(list, startIndex, true);
    });

您可能还想向函数添加事件,以表明作业已完成。

【讨论】:

  • “可能想要”有点轻描淡写,就像说您可能想在海滩上使用防晒霜。
【解决方案3】:

你可以试试这个解决方案:

var myList = new List<int>() { 8, 5, 3, 3, 3, 3, 3, 3, 4, 5, 3, 8 };
int givenIndex = 11;
int givenValue = myList[givenIndex];
bool firstFound = false, lastFound = false;
int firstIndex = givenIndex, lastIndex = givenIndex;
int index = 1;
int length = myList.Count;

while (!(firstFound && lastFound))
{
    if (!lastFound && (givenIndex + index >= length || myList[givenIndex + index] != givenValue))
    {
        lastFound = true;
        lastIndex = givenIndex + index - 1;
    }
    if (!firstFound && (givenIndex - index <= 0 || myList[givenIndex - index] != givenValue))
    {
        firstFound = true;
        firstIndex = givenIndex - index + 1;
    }

    index++;
}

Console.WriteLine("The first index is {0} and the last index is {1}.", firstIndex, lastIndex);
}

【讨论】:

    猜你喜欢
    • 2017-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    • 1970-01-01
    • 2013-12-03
    • 1970-01-01
    • 2021-12-09
    相关资源
    最近更新 更多