Хеш-таблица с ключом MultiDimensional в C#

Примечание: Я рекомендую удалить ранее установленный пакет IGV перед выполнением следующих шагов, чтобы избежать конфликтов. Просто выполните:

blockquote>
$ sudo apt remove --purge igv

Сначала вам нужно установить хотя бы Java 11 (из-за несовместимости с предыдущими версиями).

Установка JRE / JDK по умолчанию

Самый простой вариант установки Java - использовать версию, поставляемую с Ubuntu. По умолчанию Ubuntu 18.04 включает в себя Open JDK, который является вариантом JRE и JDK с открытым исходным кодом.

Чтобы установить эту версию, сначала обновите индекс пакета и обновите вашу систему:

$ sudo apt update && apt upgrade

Далее, проверьте, установлена ​​ли Java уже:

$ java -version

Если Java ] не в настоящее время установлен, вы увидите вывод, подобный следующему:

bash: java: Command not found.

Выполните следующую команду для установки OpenJDK:

$ sudo apt install default-jre

Эта команда установит Java Среда выполнения (JRE). После этого вы сможете запустить почти все программное обеспечение Java.

Теперь проверьте установку с помощью:

$ java -version

Вы увидите следующие выходные данные (версии могут отличаться):

openjdk version "11.0.3" 2019-04-16
OpenJDK Runtime Environment (build 11.0.3+1-Ubuntu-3ubuntu1)
OpenJDK 64-Bit Server VM (build 11.0.3+1-Ubuntu-3ubuntu1, mixed mode)

Следующий шаг - [ 1115] загрузите IGV и разархивируйте файл в любое место по вашему выбору (например, в /opt).

Затем откройте этот каталог в терминале (через «Открыть в терминале» ) или запустите терминал и переключитесь в каталог с помощью команды cd (имя каталога может отличаться) :

$ cd /opt/IGV_Linux_2.5.0

Чтобы запустить IGV (из командной строки), выполните следующее:

$ java --module-path=lib -Xmx4g @igv.args --module=org.igv/org.broad.igv.ui.Main

В качестве альтернативы, вы можете запустить IGV со скриптом igv.sh внутри IGV_Linux_2.5.0 каталог. Возможно, вам придется сначала выполнить исполняемый скрипт, набрав:

$ sudo chmod a+x igv.sh

Примечание: Командная строка стала более сложной с Java 11 по сравнению с предыдущими версиями. [Тысяча сто тридцать одна]

62
задан Scott Schulthess 27 March 2009 в 14:18
поделиться

13 ответов

Я думаю, что лучший подход должен инкапсулировать много полей Вашего многомерного ключа в класс / структура. Например,

struct Key {
  public readonly int Dimension1;
  public readonly bool Dimension2;
  public Key(int p1, bool p2) {
    Dimension1 = p1;
    Dimension2 = p2;
  }
  // Equals and GetHashCode ommitted
}

Теперь можно создать и использовать нормальный HashTable и использовать эту обертку в качестве Ключа.

68
ответ дан JaredPar 24 November 2019 в 16:37
поделиться

Вот пример, можно использовать нормальную Хеш-таблицу вместо той, которую я использовал.

0
ответ дан leppie 22 September 2019 в 07:04
поделиться

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

IDictionary<string, int> values = new Dictionary<string, int>();
int i = ...;
bool b = ...;
string key = string.Concat(i, '\0', b);
values[key] = 555;

Для инкапсуляции этого немного лучше, Вы могли перенести словарь:

public class MyDict
{
    private readonly IDictionary<string, int> values = new Dictionary<string, int>();

    public int this[int i, bool b]
    {
        get
        {
            string key = BuildKey(i, b);
            return values[key];
        }

        set
        {
            string key = BuildKey(i, b);
            values[key] = value;
        }
    }

    private static string BuildKey(int i, bool b)
    {
        return string.Concat(i, '\0', b);
    }
}

Для создания этого более устойчивым инкапсулируйте составной ключ как тип, например, класс, который содержит эти два поля, гарантируя, чтобы Вы переопределили Равняние () и GetHashCode () методы правильно.

0
ответ дан Paul Ruane 24 November 2019 в 16:37
поделиться

Перенесите свой двумерный ключ в отдельном type и используйте тот тип в качестве ключа. Также рассмотрите переопределение GetHashCode() и Equals() методы. Предпочтительно используйте Dictionary<> вместо HashTable так как, по-видимому, можно использовать это.

0
ответ дан bruno conde 24 November 2019 в 16:37
поделиться

Вы могли использовать a Dictionary<KeyValuePair<int,bool>,int>?

0
ответ дан Andrew Hare 24 November 2019 в 16:37
поделиться

Вы смогли к "двойному вложенному множеству" свои хеш-таблицы - другими словами, Ваш основной Словарь имеет тип Dictionary<int, Dictionary<bool, my_return_type>>.

Это выполняет Вашу цель способности использовать двойную нотацию скобки в Вашем первом фрагменте кода.

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

0
ответ дан Mike 24 November 2019 в 16:37
поделиться

Вам нужен ключевой класс для словаря, который реализует gethashcode правильно. И можно расширить словарь, чтобы позволить Вам получить доступ к нему дружественный путь.

класс пары ключей

public class KeyPair<Tkey1, Tkey2>
{
    public KeyPair(Tkey1 key1, Tkey2 key2)
    {
        Key1 = key1;
        Key2 = key2;
    }

    public Tkey1 Key1 { get; set; }
    public Tkey2 Key2 { get; set; }

    public override int GetHashCode()
    {
        return Key1.GetHashCode() ^ Key2.GetHashCode();
    }
    public override bool Equals(object obj)
    {
        KeyPair<Tkey1, Tkey2> o = obj as KeyPair<Tkey1, Tkey2>;
        if (o == null)
            return false;
        else
            return Key1.Equals(o.Key1) && Key2.Equals(o.Key2);
    }
}

расширьте Dictonary <>

public class KeyPairDictonary<Tkey1, Tkey2, Tvalue> 
    : Dictionary<KeyPair<Tkey1, Tkey2>, Tvalue>
{
    public Tvalue this[Tkey1 key1, Tkey2 key2]
    {
        get
        {
            return this[new KeyPair<Tkey1, Tkey2>(key1, key2)];
        }
        set
        {
            this[new KeyPair<Tkey1, Tkey2>(key1, key2)] = value;
        }
    }
}

и Вы используете его как это

        KeyPairDictonary<int, bool, string> dict = 
            new KeyPairDictonary<int, bool, string>();
        dict[1, false] = "test";
        string test = dict[1, false];
4
ответ дан AndreasN 24 November 2019 в 16:37
поделиться

Я предложил бы небольшую вариацию на решение jachymko, которое позволит Вам стараться не создавать класс для пар ключей. Вместо этого перенесите частный словарь словарей, как так:

public class MultiDictionary<K1, K2, V>
{
    private Dictionary<K1, Dictionary<K2, V>> dict = 
        new Dictionary<K1, Dictionary<K2, V>>();

    public V this[K1 key1, K2 key2]
    {
        get
        {
            return dict[key1][key2];
        }

        set
        {
            if (!dict.ContainsKey(key1))
            {
                dict[key1] = new Dictionary<K2, V>();
            }
            dict[key1][key2] = value;
        }
    }
}
5
ответ дан 24 November 2019 в 16:37
поделиться

Я думаю, что это могло бы быть ближе к тому, что Вы ищете...

var data = new Dictionary<int, Dictionary<bool, int>>();
16
ответ дан Jason Punyon 24 November 2019 в 16:37
поделиться

Как насчет того, чтобы использовать регулярный Словарь с некоторой структурой Кортежа как ключ?

public class TwoKeyDictionary<K1,K2,V>
{
    private readonly Dictionary<Pair<K1,K2>, V> _dict;

    public V this[K1 k1, K2 k2]
    {
        get { return _dict[new Pair(k1,k2)]; }
    }

    private struct Pair
    {
        public K1 First;
        public K2 Second;

        public override Int32 GetHashCode()
        {
            return First.GetHashCode() ^ Second.GetHashCode();
        }

        // ... Equals, ctor, etc...
    }
}
23
ответ дан 24 November 2019 в 16:37
поделиться

Я предложил бы, чтобы Вы создали маленький пользовательский класс, выставляющий bool и международные свойства, и переопределили его GetHashCode, и Равняется методам, затем используйте это в качестве ключа.

1
ответ дан David M 24 November 2019 в 16:37
поделиться

Посмотрите, этот код работает отлично:

    public Form1()
    {
            InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

        this.Services = new Dictionary<object, Hashtable>();
        this.Services.Add("array1", new Hashtable());

        this.Services["array1"]["qwe"] = "123";
        this.Services["array1"][22] = 223;

        object zz = null;
        zz = this.Services["array1"]["qwe"];
        MessageBox.Show(zz.ToString()); // shows qwe

        zz = this.Services["array1"][22];
        MessageBox.Show(zz.ToString()); // shows 22
    }

Теперь нам просто нужна оболочка, чтобы не делать это вручную.Services.Add ("array1", new Hashtable ());

0
ответ дан 24 November 2019 в 16:37
поделиться

По сути, вам нужно использовать встроенную хеш-таблицу. Если вы думаете о своем вопрос, хеш-таблица с двумя ключами - это функция с двумя независимыми переменных, и f (x, y) двумерна по определению.

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

Пара препятствий:

  • Вы хотите перебрать его, поэтому вам нужно перезаписать метод GetEnumerator () . И вам нужен собственный итератор, который будет правильно выполнять итерацию в двух измерениях.
  • Вам нужно выполнить дополнительную проверку, чтобы убедиться, что нет дубликатов.

Я включил свой код, чтобы сделать это:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Windows.Forms;

namespace YourProjectNameHere
{
    public class Hashtable2D
    {
        /// <summary>
        /// This is a hashtable of hashtables
        /// The X dim is the root key, and the y is the internal hashes key
        /// </summary>
        /// 
        private Hashtable root = new Hashtable();
        public bool overwriteDuplicates = false;
        public bool alertOnDuplicates = true;

        public void Add(object key_x, object key_y, object toStore)
        {
            if(root[key_x]!=null)//If key_x has already been entered 
            {
                Hashtable tempHT = (Hashtable)root[key_x];//IF the hash table does not exist then focus will skip to the catch statement
                if (tempHT[key_y] == null)  tempHT.Add(key_y, toStore);
                else handleDuplicate(tempHT, key_y, toStore);
            }else{//Making a new hashtable 
                Hashtable tempHT = new Hashtable();
                tempHT.Add(key_y, toStore);
                root.Add(key_x, tempHT);
            }

        }

        public void Remove(object key_x, object key_y)
        {
            try{
                ((Hashtable)root[key_x]).Remove(key_y);
            }catch(Exception e){
                MessageBox.Show("That item does not exist");
            }

        }

        public void handleDuplicate (Hashtable tempHT, object key_y, object toStore)
        {
            if (alertOnDuplicates) MessageBox.Show("This Item already Exists in the collection");

            if (overwriteDuplicates)
            {
                tempHT.Remove(key_y);
                tempHT.Add(key_y,toStore);
            }
        }

        public object getItem(object key_x, object key_y)
        {
            Hashtable tempHT = (Hashtable)root[key_x];
            return tempHT[key_y];
        }

        public ClassEnumerator GetEnumerator()
        {
            return new ClassEnumerator(root);
        }

        public class ClassEnumerator : IEnumerator
        {
            private Hashtable ht;
            private IEnumerator iEnumRoot;
            private Hashtable innerHt;
            private IEnumerator iEnumInner;

            public ClassEnumerator(Hashtable _ht)
            {
                ht = _ht;
                iEnumRoot = ht.GetEnumerator();

                iEnumRoot.MoveNext();//THIS ASSUMES THAT THERE IS AT LEAST ONE ITEM

                innerHt = (Hashtable)((DictionaryEntry)iEnumRoot.Current).Value;
                iEnumInner = innerHt.GetEnumerator();
            }

            #region IEnumerator Members

            public void Reset()
            {
                iEnumRoot = ht.GetEnumerator();
            }

            public object Current
            {
                get
                {
                    return iEnumInner.Current; 
                }
            }

            public bool MoveNext()
            {
                if(!iEnumInner.MoveNext())
                {
                    if (!iEnumRoot.MoveNext()) return false;
                    innerHt = (Hashtable)((DictionaryEntry)iEnumRoot.Current).Value;
                    iEnumInner = innerHt.GetEnumerator();
                    iEnumInner.MoveNext();
                }
                return true;
            }

            #endregion
        }

    }
}
1
ответ дан 24 November 2019 в 16:37
поделиться
Другие вопросы по тегам:

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