Присоединение/слияние к массивам в C#

Если вы можете обновить, чтобы использовать implementation 'com.zopim.android:sdk:1.4.2', который решил проблему для меня.

5
задан Bergius 13 February 2009 в 10:04
поделиться

5 ответов

Это очень inefficent в данный момент - все те вызовы к ElementAt могли проходить целую последовательность (насколько им нужно к), каждый раз. (Это зависит от реализации последовательности.)

Однако я нисколько не уверен, что даже понимаю то, что делает этот код (использующий циклы foreach, почти наверняка сделал бы это более ясным, как будет, выполняя итерации форвардов вместо назад. Вы могли дать некоторый демонстрационный вход? и ожидаемые выводы?

Править: Хорошо, я думаю, что вижу то, что продолжается здесь; Вы эффективно вертитесь 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 массивом для начала, это откровенно было бы легче.

Править: Хорошо, принятие мы можем использовать массивы вместо этого:

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
ответ дан 14 December 2019 в 09:01
поделиться

Как насчет:

        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;
    }

или немного редактируя ответ стрельбы по тарелочкам (это не работало на меня):

        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
ответ дан 14 December 2019 в 09:01
поделиться

Вот некоторая элегантность. Это длиннее, чем мне нравится, но это очень доступно для исследования.

    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;
    }

И вот вспомогательные методы, которые я использовал.

   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);
    }

Отказ от ответственности: если Вы называете Центр с непрямоугольной структурой, я не знаю/забочусь то, что произойдет.

1
ответ дан 14 December 2019 в 09:01
поделиться

Если я не пропускаю что-то, Вам не нужен код для дублирования массивов - они - объекты самостоятельно и не собираются исчезать неожиданно.

Использовать 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 вместо строки [] - по моему скромному мнению, Вы найдете это более гибким, чем использование массивов.

Кроме того, тип возврата использует Интерфейс.

Обновленный: John Skeet сделал правильное замечание (см. комментарий ниже), что массивы изменяемы, и это могло бы быть проблемой. Посмотрите ниже для легкого изменения для создания новых массивов:

    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
ответ дан 14 December 2019 в 09:01
поделиться

Это является не совсем столь общим, как Вы попросили, но это присоединяется к двум enumerables в счетную из пар. Это довольно тривиально для превращения того результата, счетного в словарь.

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
ответ дан 14 December 2019 в 09:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: