简体   繁体   中英

Find Index of List of Tuples from 1 item

Please consider a List of Tuples in C#. This relates to the original Tuple (not Value Tuple). How can I get the index of the List, if I know one of the Items within the List of Tuples?

        List<Tuple<double, int>> ListOfTuples2 = new 
        List<Tuple<double, int>>();

        double doubleTuple = 5000;
        int intTuple = 7;

        ListOfTuples2.Add(Tuple.Create(doubleTuple, intTuple));
        ListOfTuples2.Add(Tuple.Create(5000.00, 2));
        ListOfTuples2.Add(Tuple.Create(5000.25, 3));
        ListOfTuples2.Add(Tuple.Create(5000.50, 4));
        ListOfTuples2.Add(Tuple.Create(5000.25, 5));


        /* How can I get the Index of the List if 
        doubleTuple = 5000.25 ?  */  

You can use the FindIndex method of the list accepting a predicate as argument

int index = ListOfTuples2.FindIndex(t => t.Item1 == 5000.25);
if (index > = 0) {
    // found!
}

FindIndex returns -1 if no such item is found.


But you might consider using a dictionary instead. If the collection is big, it finds entries much faster than a list. The retrieval times in Big O notation : List<T> is O(n) , Dictionary<K,V> is O(1) . However, items in a dictionary are not ordered and have no index. In addition, keys must be unique. If you need ordered items, stick to the list.

var dict = new Dictionary<double, int>{
    [doubleTuple] = intTuple,
    [5000.00] = 2,
    [5000.25] = 3,
    [5000.50] = 4,
    [5000.25] = 5
}

if (dict.TryGetValue(5000.25, out int result)) {
    // result is 3; and contains the value, not the index.
}

You can also add entries with

dict.Add(5000.75, 8);

If you are sure that the dictionary contains an entry, you can simply retrieve it with

int result = dict[5000.25];

Also, if you are dealing with prices, consider using the decimal type. If has been created specifically for financial and monetary calculations. The double type stores the values as binary numbers. 0.1 (decimal) is 0.000110011001100110011001100110011... (binary), ie, double introduces a rounding error, solely by converting a decimal constant into its binary representation, whereas decimal stores each decimal of the constant as is. double is okay (and faster) for scientific calculations. It makes no difference whether a temperature is 29.7 or 29.69999999999 degrees, since you can measure it with a very limited precision anyway (maybe 1%).


C# 7.0 has added ValueTuple types plus a simple syntax for tuple types and tuple values. Consider replacing the Tuple class with this new feature.

var listOfValueTuples = new List<(double, int)> {
    (doubleTuple, intTuple),
    (5000.00, 2),
    (5000.25, 3),
    (5000.50, 4),
    (5000.25, 5)
};

In case you want to get all indexes you can write following code:

var indexes = ListOfTuples2.Select((tuple, index) => new {tuple, index}).Where(o => Math.Abs(o.tuple.Item1 - 5000.25) < 1e-5).Select(o => o.index - 1);
foreach (var index in indexes)
{
    Console.WriteLine(index);
}

Note that comparing two floats can return unpredictable results, so I used comparing using Math.Abs method

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM