Home > database >  How do I pick out values between a duplicate value in a collection?
How do I pick out values between a duplicate value in a collection?

Time:09-30

I have a method that returns a collection that has a duplicate value.

static List<string> GenerateItems()
{
    var _items = new List<string>();
    _items.Add("Tase");
    _items.Add("Ray");
    _items.Add("Jay");
    _items.Add("Bay");
    _items.Add("Tase");
    _items.Add("Man");
    _items.Add("Ran");
    _items.Add("Ban");

    return _items;
}

I want to search through that collection and find the first place that duplicate value is located and start collecting all the values from the first appearance of the duplicate value to its next appearance. I want to put this in a collection but I only want the duplicate value to appear once in that collection.

This is what I have so far but.

static void Main(string[] args)
{
    string key = "Tase";
    var collection = GenerateItems();
    int index = collection.FindIndex(a => a == key);

    var matchFound = false;
    var itemsBetweenKey = new List<string>();

    foreach (var item in collection)
    {
        if (item == key)
        {
            matchFound = !matchFound;
        }
        if (matchFound)
        {
            itemsBetweenKey.Add(item);
        }
    }
    foreach (var item in itemsBetweenKey)
    {
        Console.WriteLine(item);
    }

    Console.ReadLine();
}

There must be an easier way of doing this. Perhaps with Indexing or a LINQ query?

CodePudding user response:

You can do something like that

string key = "Tase";
var collection = GenerateItems();
int indexStart = collection.FindIndex(a => a == key);
int indexEnd = collection.FindIndex(indexStart 1, a => a == key);

var result = collection.GetRange(indexStart, indexEnd-indexStart);

CodePudding user response:

You can use linq select and group by to find the first index and last index of all duplicates (Keep in mind if something is in the list more then 2 times it would ignore the middle occurences.

But I personally think the linq for this seems overcomplicated. I would stick with simple for loops and if statements (Just turn it into a method so it reads better)

Here is a solution with Linq to get all duplicate and all values between those duplicates including itself once as you mentioned.

var collection = GenerateItems();
var Duplicates = collection.Select((x,index) => new { index, value = x })
                           .GroupBy(x => x.value)//group by the strings
                           .Where(x => x.Count() > 1)//only take duplicates
                           .Select(x=>new {
                                       Value = x.Key, 
                                       FirstIndex = x.Min(y=> y.index),//take first occurenc
                                       LastIndex = x.Max(y => y.index)//take last occurence
                           }).ToList();

var resultlist = new List<List<string>>();

foreach (var duplicaterange in Duplicates)
            resultlist .Add(collection.GetRange(duplicaterange.FirstIndex, duplicaterange.LastIndex - duplicaterange.FirstIndex));

CodePudding user response:

slightly adjusted version of @Klamsi

    var key = "Tase";
    var collection = GenerateItems();
    var index = collection.IndexOf(key);
    var index2 = collection.LastIndexOf(key);
    
    var itemsInBetween = collection.GetRange(index, index2 - index);
    
    foreach(var item in itemsInBetween){
        Console.WriteLine(item);
    }

CodePudding user response:

Try this function

public List<string> PickOut(List<string> collection, string key)
{
    var index = 0;
    foreach (var item in collection)
    {
        if (item == key)
        {
            return collection.Skip(index).TakeWhile(x=> x != key).ToList();
        }
        index  ;
    };
    return null;
}

CodePudding user response:

First finding the duplicate key then find the second occurrence of the item and then take result.

var firstduplicate = collection.GroupBy(x => x)
                    .Where(g => g.Count() > 1)
                    .Select(g => g.Key).First();

var indices = collection.Select((b, i) => b == firstduplicate ? i : -1).Where(i => i != -1).Skip(1).FirstOrDefault();
if (indices>0) 
{
    var result = collection.Take(indices).ToList();
}
  • Related