Существует ли структура данных, которая содержит наборы данных в.NET?

Я ищу структуру данных, подобную словарю, который возвращает набор всех связанных объектов к ключу.

Например, я использовал бы его как это:

var data = new FancyDataStructure();

data.Add(new string[] {"Elizabeth", "Liz", "Betty"});
data.Add(new string[] {"Bob", "Robert", "Rob"});

string[] alternateNames1 = data["Betty"];
string[] alternateNames2 = data["Liz"]

В этом экземпляре alternateNames1 был бы массивом, содержащим "Liz" и "Elizabeth", и alternateNames2 будет массивом, содержащим "Elizabeth" и "Betty".

Я не хочу переосмысливать это, но я не мог найти примеры такой структуры.

Обновление

Спасибо тем, которые записали обратно с предложениями. Многие люди предложили использовать некоторую версию Dictionary<string, IEnumerable<string>>. В настоящее время я использую этот подход, но он на самом деле не выполняет требование, не будучи ужасно трудным поддержать. Каждое значение в каждом списке должно смочь функционировать как ключ к любому значению, когда-либо добавленному к нему в наборе.

Таким образом, учитывая следующее:

data.Add(new string[] {"Elizabeth", "Liz"}
data.Add(new string[] {"Liz", "Betty"}
alternates = data["Betty"];

Я ожидал бы, что альтернативы теперь будут содержать "Elizabeth" и "Liz".

Выглядит, как будто мне, возможно, просто придется создать такую структуру для удовлетворения моим потребностям. Сохраните прибытие идей хотя!

Brian

8
задан Brian Vallelunga 10 February 2010 в 01:24
поделиться

12 ответов

Ваша проблема звучит так, как будто это действительно проблема построения графиков. Считайте, что имена - это узлы, а принадлежность к множеству - ребра. С этой точки зрения, вам нужна структура данных, которая хорошо справляется с разреженными графами, например список смежности. Это, конечно, похоже на то, что вы уже делаете с Dictionary>, но размышление об этом в таком ключе может привести вас к некоторым полезным реализациям и алгоритмам.

1
ответ дан 6 December 2019 в 02:24
поделиться

Что-то вроде этого кажется достаточно простым.

var data = new List<string[]>();

data.Add(new string[] {"Elizabeth", "Liz", "Betty"});
data.Add(new string[] {"Bob", "Robert", "Rob"});

var alternateNames1 = data.Where(x =>x.Contains("Betty")).Select(x => x.Where(y => y != "Betty"));
0
ответ дан 6 December 2019 в 02:24
поделиться

Я бы просто использовал тип Dictionary > . Чтобы построить эту структуру из списка списков, у вас может быть такой код:

var alternateNames = new string[][] {
    new string[] { "Elizabeth", "Liz", "Betty" },
    new string[] { "Bob", "Robert", "Rob" }, };
var altNameLookup = 
    (
        from nameList in alternateNames
        from name in nameList
        select new { 
            Name = name, NameList = nameList.Except(new string[] { name } ) }
    ).ToDictionary(o => o.Name, o => o.NameList);
0
ответ дан 6 December 2019 в 02:24
поделиться

Де-факто стандарт alt.net находится в Iesi.Collections, но библиотека базовых классов имеет только HashSet в dotnet 3.5 или выше.

Я использовал в linq предложения типа "group by", чтобы легко удалять дубликаты из произвольных IEnumerable коллекций, но это не дает семантики набора.

HashSet<> близок к тому, что вы хотите.

Исходя из ваших требований, я не думаю, что есть что-то готовое, что могло бы сопоставить строки с уже существующими коллекциями; В основном, вам придется написать класс, который принимает метод типа StoreAssociations<>(IEnumerable<> names), преобразует IEnumerable в HashSet и итерирует каждый элемент в HashSet, чтобы добавить отображение в IDictionary> на вновь созданный хэшсет.

0
ответ дан 6 December 2019 в 02:24
поделиться

Как насчет пары структур данных: Dictionary и Dictionary >

Чтобы добавить пару ключей (a, b) [вы можете разложить большее сложение на пары (1 + 2, 2 + 3, ...] действуйте следующим образом: -

Найдите a и b в первом словаре.
Если ни один из них не существует, создайте новый Guid и добавьте (a, g) и (b, g) в первый словарь и (g, List {a}) и (g, List {b}) ко второму словарю.

Если один существует, скажем, a, возьмите из него руководство (g), добавьте другой (b, g) в первый словарь и закрепите b в конце списка, найденного в [g] во втором словаре.

Если оба существуют И у них один и тот же гид - делать нечего.

Если оба существуют и у них разные руководства, вам нужно объединить два набора // Это то, чего не хватает в большинстве других предлагаемых решений, // поэтому выберите Guid, который нужно удалить, возьмите его из второго словаря, добавьте список строк к другой записи, а затем удалите эту запись. Наконец, отметьте все слова в первом словаре, которые были в этом списке.

Чтобы получить все связанные слова, найдите Guid в первом словаре и возьмите список из второго словаря.

Конечно, статическое увеличивающееся длинное значение, вероятно, будет работать лучше, чем Guid.

0
ответ дан 6 December 2019 в 02:24
поделиться

Попробуйте использовать словарь, например:

Dictionary<string, List<string>>

Итак, словарь строковых ключей со значениями List

-1
ответ дан 6 December 2019 в 02:24
поделиться

Я написал код, не знаю, насколько он эффективен, но я думаю, что он делает то, что вы хотите.

Это ваша структура

class FancyDataStructure
{
    private IDictionary<string, HashSet<string>> dictionary 
        = new Dictionary<string, HashSet<string>>();

    public void Add(params string[] names)
    {
        HashSet<string> set = new HashSet<string>(names);
        for (int i = 0; i < names.Length; i++)
        {
            if (!dictionary.ContainsKey(names[i]))
            {
                dictionary.Add(names[i], set);
            }
            else
            {
                HashSet<string> union = 
                new HashSet<string>(set.Union<string>(dictionary[names[i]]));
                set = union;
                foreach (string oldName in dictionary[names[i]])
                {
                    dictionary[oldName] = union;
                }
                for (int j = 0; j < i; j++)
                {
                    if (!dictionary.ContainsKey(names[j]))
                    {
                        dictionary.Add(names[j], union);
                    }
                }
            }
        }
    }

    public string[] this[string key]
    {
        get
        {
            List<string> result = dictionary[key].ToList<string>();
            result.Remove(key);
            return result.ToArray();
        }
    }
}

, и вы можете использовать ее, например,

    static void Main(string[] args)
    {

        FancyDataStructure data = new FancyDataStructure();

        data.Add("Elizabeth", "Liz");
        data.Add("Liz", "Betty");

        string[] alternates = data["Betty"];
        foreach (var item in alternates)
        {
            Console.WriteLine(item);
        }
    }
0
ответ дан 6 December 2019 в 02:24
поделиться

Пространство имен System.Collections.Generic и System.Collections загружены словарями пар ключ-значение, сортированными словарями, объектами List и многим другим.

System.Collections.Generic.Dictionary<int, string> dic = new Dictionary<int, string>();
        dic.Add(1, test);

или вложенный список внутри словаря

Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>();
List<string> alternatives = new List<string>();
alternatives.Add("Brenda");
dic.Add("Betty", alternatives);
1
ответ дан 6 December 2019 в 02:24
поделиться

Просто мысль в другом направлении - строго типизированные наборы данных, кажется, имеют много преимуществ. И сериализованные в виде байтовых массивов, они довольно быстро перемещают многомерно структурированные данные.

Итерация и возможности Linq в некотором роде встроены.

Возможно, это излишне для многих вещей, но у меня есть несколько мест, где я хранил весь набор данных в одном столбце varbinary (max) в SQL.

1
ответ дан 6 December 2019 в 02:24
поделиться

По сути, у вас есть словарь, в котором несколько ключей отображаются на одно и то же значение. Нет встроенной структуры данных, которая поддерживает нужную вам операцию, но ее легко представить в виде Dictionary {string, HashSet {string}} в .NET:

static void AddNames(Dictionary<string, HashSet<string>> map, params string[] names)
{
    for (int i = 0; i < names.Length; i++)
    {
        HashSet<string> value;
        if (!map.TryGetValue(names[i], out value))
        {
            value = new HashSet<string>();
            map.Add(names[i], value);
        }

        for (int j = 0; j < names.Length; j++)
        {
            value.Add(names[j]);
        }
    }
}

static void Main(string[] args)
{
    Dictionary<string, HashSet<string>> names = new Dictionary<string,HashSet<string>>();
    AddNames(names, "Chris", "Christopher");
    AddNames(names, "Christina", "Chrissy", "Chris");

    HashSet<string> relatedToChris = names["Chris"];                // gets "Chris", "Christina", "Chrissy", "Christopher";
    HashSet<string> namesRelatedToChristinia = names["Christina"];  // gets "Christina", "Chrissy", "Chris";
}

Вы можете представить свою структуру данных как ориентированный граф, в котором каждый узел имеет ребро, связанное с его именем. Поскольку существует n ^ 2 ребер, словарю требуется время O (n ^ 2) для вставки и памяти. Невозможно сократить время поиска до чего-то лучшего.

К счастью, поскольку он реализован как словарь, поиск по-прежнему O (1). Удаляются O (m), где m - количество значений, связанных с ключом.

0
ответ дан 6 December 2019 в 02:24
поделиться

Или, поскольку List является ссылочным типом, вы можете сделать следующее ...

Dictionary<string, List<string>> dict = new ...

Выполните следующие действия: -

Чтобы добавить одну ассоциацию (a = b) {разложено из списка эквивалентностей}

Искать a и b в Словаре

Если ни один не существует

dict.Add(a, new List<string>(){a}); dict.Add(b, new List<string>(){b});

Если один существует, скажем, a

var list = dict[a];
list.Add(b);
dict.Add(b, list);

Если оба существуют и списки являются то же самое (сравнение объектов), вы сделали.

Если оба существуют и списки разные:

var list1 = dict[a];
var list2 = dict[b];
list1.AddRange(list2);
dict.Remove(b);
dict.Add(b, list1);
0
ответ дан 6 December 2019 в 02:24
поделиться
Другие вопросы по тегам:

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