Merge / Merge Arrays in C #

I have two or more arrays - one with identifiers, one or more with string values. I want to combine them into a hash table so that I can search for values ​​by ID.

The following function does the job, but the shorter and weaker version (LINQ?) Will be nice:

Dictionary<int, string[]> MergeArrays( IEnumerable<int> idCollection,
                                       params IEnumerable<string>[] valueCollections )
{
    var dict = new Dictionary<int, string[]>();

    var idL = idCollection.Count();
    while ( idL-- > 0 )
    {
        dict[idCollection.ElementAt( idL )] = new string[valueCollections.Length];

        var vL = valueCollections.Length;
        while ( vL-- > 0 )
            dict[idCollection.ElementAt( idL )][vL] = valueCollections[vL].ElementAt( idL );
    }

    return dict;
}

Any ideas?

+5
source share
5 answers

This is currently very inefficient - all of these calls to ElementAt can go through the entire sequence (as necessary) each time. (It depends on the implementation of the sequence.)

, , , ( foreach , , ). ?

EDIT: , , , ; valueCollections. , - :

static Dictionary<int, string[]> MergeArrays(
    IEnumerable<int> idCollection,
    params IEnumerable<string>[] valueCollections)
{
    var valueCollectionArrays = valueCollections.Select
         (x => x.ToArray()).ToArray();
    var indexedIds = idCollection.Select((Id, Index) => new { Index, Id });

    return indexedIds.ToDictionary(x => Id, 
        x => valueCollectionArrays.Select(array => array[x.Index]).ToArray());
}

. idCollection , .

EDIT: , , :

static Dictionary<int, string[]> MergeArrays(
    int[] idCollection,
    params string[][] valueCollections)
{
    var ret = new Dictionary<int, string[]>();
    for (int i=0; i < idCollection.Length; i++)
    {
         ret[idCollection[i]] = valueCollections.Select
             (array => array[i]).ToArray();
    }
    return ret;
}

() - , , . , .

+3

:

        public static Dictionary<int, string[]> MergeArrays2(IEnumerable<int> idCollection,
        params IEnumerable<string>[] valueCollections)
    {
        var dict = new Dictionary<int, string[]>();
        var valEnums = (from v in valueCollections select v.GetEnumerator()).ToList();
        foreach (int id in idCollection)
        {
            var strings = new List<string>();
            foreach (var e in valEnums)
                if (e.MoveNext())
                    strings.Add(e.Current);
            dict.Add(id, strings.ToArray());
        }
        return dict;
    }

skeet ( ):

        static Dictionary<int, string[]> MergeArrays_Skeet(IEnumerable<int> idCollection,params IEnumerable<string>[] valueCollections)
    {
        var valueCollectionArrays = valueCollections.Select(x=>x.ToArray()).ToArray();
        var indexedIds = idCollection.Select((Id, Index) => new { Index, Id });
        return indexedIds.ToDictionary(x => x.Id,x => valueCollectionArrays.Select(array => array[x.Index]).ToArray());
    }
+2

- , - .

Select(), , ToDictionary(), .

:

    IDictionary<int, IEnumerable<string>> MergeArrays2(
        IEnumerable<int> idCollection,
        params IEnumerable<string>[] valueCollections)
    {
        var values = valueCollections.ToList();
        return idCollection.Select(
            (id, index) => new { Key = id, Value = values[index] })
            .ToDictionary(x => x.Key, x => x.Value);
    }

, IEnumerable [] - IMHO, , .

, .

Updated. (. ), , . :

    IDictionary<int, IEnumerable<string>> MergeArrays2(
        IEnumerable<int> idCollection,
        params IEnumerable<string>[] valueCollections)
    {
        var values = valueCollections.ToList();
        return idCollection.Select(
            (id, index) => new 
            { 
                Key = id, 
                Value = values[index].ToArray()  // Make new array with values
            })
            .ToDictionary(x => x.Key, x => x.Value);
    }
+1
source

- . , , .

    public Dictionary<int, string[]> MergeArrays(
        IEnumerable<int> idCollection,
        params IEnumerable<string>[] valueCollections
            )
    {
        Dictionary<int, int> ids = idCollection
            .ToDictionaryByIndex();
        //
        Dictionary<int, List<string>> values =
            valueCollections.Select(x => x.ToList())
            .ToList()
            .Pivot()
            .ToDictionaryByIndex();
        //
        Dictionary<int, string[]> result =
            ids.ToDictionary(
                z => z.Value,
                z => values[z.Key].ToArray()
            );

        return result;
    }

And here are the helper methods that I used.

   public static List<List<T>> Pivot<T>
        (this List<List<T>> source)
    {
        return source
            .SelectMany((it) =>
              it.Select((t, i) => new { t, i })
            )
            .GroupBy(z => z.i)
            .Select(g => g.Select(z => z.t).ToList())
            .ToList();
    }

    public static Dictionary<int, T> ToDictionaryByIndex<T>
        (this IEnumerable<T> source)
    {
        return source
            .Select((t, i) => new { t, i })
            .ToDictionary(z => z.i, z => z.t);
    }

Disclaimer: if you call Pivot with a non-rectangular structure, I don't know / care about what happens.

+1
source

This is not quite as you requested, but it combines two enumerated numbers into enumerated pairs. It is pretty trivial to turn this result into a dictionary.

public static class ExtensionMethods
{
    public static IEnumerable<Pair<TOuter, TInner>> InnerPair<TInner, TOuter>(this IEnumerable<TOuter> master,
                                                                         IEnumerable<TInner> minor)
    {
        if (master == null)
            throw new ArgumentNullException("master");
        if (minor == null)
            throw new ArgumentNullException("minor");
        return InnerPairIterator(master, minor);
    }

    public static IEnumerable<Pair<TOuter, TInner>> InnerPairIterator<TOuter, TInner>(IEnumerable<TOuter> master,
                                                                                 IEnumerable<TInner> minor)
    {
        IEnumerator<TOuter> imaster = master.GetEnumerator();
        IEnumerator<TInner> iminor = minor.GetEnumerator();
        while (imaster.MoveNext() && iminor.MoveNext())
        {
            yield return
                new Pair<TOuter, TInner> { First = imaster.Current, Second = iminor.Current };
        }
    }
}


public class Pair<TFirst, TSecond>
{
    public TFirst First { get; set; }
    public TSecond Second { get; set; }
}
0
source

All Articles