SamuraiJack
SamuraiJack

Reputation: 5549

How to find the next element in a generic List?

This is my Generic List:

public class TagType { public string FieldTag; public int Position; }

List<TagType<dynamic>> TagList = new List<TagType<dynamic>>();

TagList.Add(new TagType<dynamic>() { FieldTag = "ID", Position = posIdStr });
TagList.Add(new TagType<dynamic>() { FieldTag = "PT", Position = posPtStr });
TagList.Add(new TagType<dynamic>() { FieldTag = "ID", Position = posIdStr });
TagList.Add(new TagType<dynamic>() { FieldTag = "EC", Position = posECStr });

I am trying to get Position value for the FieldTag that comes after (for eg: PT). How do I do this?

Upvotes: 0

Views: 1074

Answers (4)

paparazzo
paparazzo

Reputation: 45096

public Position? GetNextPosition(string FieldTagVal)
{
    bool returnNext = false;
    foreach(TagType t in TagList) 
    {
       if (returnNext) return t.Position;
       if (t.FieldTag == FieldTagVal) returnNext = true;
    }
    return null;
}

Upvotes: 0

Michal Ciechan
Michal Ciechan

Reputation: 13898

Unfortunately each time you do a search you will have to iterate over the list, find the field tag you are looking for, then go to the next element and get the position value. e..: An O(n) for lookup solution:

    private static object SearchPosition(List<TagType<object>> tagList, string fieldTag)
    {
        var i = tagList.FindIndex(x => x.FieldTag == "PT");

        if (i >= 0 && i < tagList.Count)
        {
            return tagList[i + 1].Position;
        }
    }

And test:

    [Test]
    public void FieldTagTest()
    {
        var res = SearchPosition(_tagList, "PT");

        res.ToString().Should().Be("ID2");
    }

If your list does not change often, you should build a Dictionary<string,int> with the FieldTag as Keyand the list index position as value. Ofcourse each time you modify the list you would need to build this index again.

An O(1) solution is:

    private static object SearchPositionUsingIndex(List<TagType<object>> tagList, string fieldTag)
    {
        // You would save this index, and build it only once, 
        // or rebuild it whenver something changes.
        // you could implement custom index modifications.
        var index = BuildIndex(tagList);

        int i;
        if (!index.TryGetValue(fieldTag, out i)) return null;
        if (i + 1 >= tagList.Count) return null;
        return tagList[i + 1].Position;
    }

    private static Dictionary<string, int> BuildIndex(List<TagType<object>> tagList)
    {
        var index = new Dictionary<string, int>();

        for (int i = 0; i < tagList.Count; i++)
        {
            var tag = tagList[i];
            if (!index.ContainsKey(tag.FieldTag)) index.Add(tag.FieldTag, i);
        }
        return index;
    }

And test:

    [Test]
    public void FieldTagTestUsingIndex()
    {
        var res = SearchPositionUsingIndex(_tagList, "PT");

        res.ToString().Should().Be("ID2");
    }

Or you could use a 1 line LINQ method, which is also O(n):

    [Test]
    public void FieldTagTestLinq()
    {
        var res = SearchUsingLinq();

        res.ToString().Should().Be("ID2");
    }

    private object SearchUsingLinq()
    {
        var p = _tagList.SkipWhile(x => x.FieldTag != "PT").Skip(1).FirstOrDefault();
        return p != null ? p.Position : null;
    }

TestSetup

public class SO29047477
{
    private List<TagType<object>> _tagList;

    [SetUp]
    public void TestSetup()
    {
        _tagList = new List<TagType<dynamic>>();

        _tagList.Add(new TagType<dynamic>() { FieldTag = "ID", Position = "ID1"});
        _tagList.Add(new TagType<dynamic>() { FieldTag = "PT", Position = "PT1" });
        _tagList.Add(new TagType<dynamic>() { FieldTag = "ID", Position = "ID2" });
        _tagList.Add(new TagType<dynamic>() { FieldTag = "EC", Position = "EC1" });

    }
}

Upvotes: 1

Farhad Jabiyev
Farhad Jabiyev

Reputation: 26655

If you want to get next element's Position after each item with FieldTag PT, then you can solve it in one or two lines with LINQ:

var resultTag = TagList.SkipWhile(x => x.FieldTag != "PT").Skip(1).FirstOrDefault();
var resultPosition = resultTag == null ?  0 : resultTag.Position;

Additional:
If you want to cast it to int then just cast it explicitly.

var resultTag = TagList.SkipWhile(x => x.FieldTag != "PT").Skip(1).FirstOrDefault();
int resultPosition = resultTag == null ?  0 : (int)resultTag.Position;

Upvotes: 0

xanatos
xanatos

Reputation: 111910

You find the index of PT and add 1? (but remember to check that the index + 1 < the length of the List)

// Find the index of PT
int ix = TagList.FindIndex(x => x.FieldTag == "PT");

// index found
if (ix != -1)
{
    // Check that index + 1 < the length of the List
    if (ix + 1 < TagList.Count)
    {
        var position = TagList[ix + 1]; // Add 1
    }
}

Upvotes: 2

Related Questions