Примечание: Я рекомендую удалить ранее установленный пакет 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 по сравнению с предыдущими версиями. [Тысяча сто тридцать одна]
Я думаю, что лучший подход должен инкапсулировать много полей Вашего многомерного ключа в класс / структура. Например,
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 и использовать эту обертку в качестве Ключа.
Вот пример, можно использовать нормальную Хеш-таблицу вместо той, которую я использовал.
Быстрый и грязный путь состоял бы в том, чтобы создать составной ключ из этих двух сведений, например.
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 () методы правильно.
Перенесите свой двумерный ключ в отдельном type
и используйте тот тип в качестве ключа. Также рассмотрите переопределение GetHashCode()
и Equals()
методы. Предпочтительно используйте Dictionary<>
вместо HashTable
так как, по-видимому, можно использовать это.
Вы могли использовать a Dictionary<KeyValuePair<int,bool>,int>
?
Вы смогли к "двойному вложенному множеству" свои хеш-таблицы - другими словами, Ваш основной Словарь имеет тип Dictionary<int, Dictionary<bool, my_return_type>>
.
Это выполняет Вашу цель способности использовать двойную нотацию скобки в Вашем первом фрагменте кода.
Конечно, сторона управления немного более хитра. Каждый раз, когда Вы добавляете запись, необходимо протестировать, если основной словарь содержит словарь для первичного ключа, и добавьте, что новый словарь в противном случае затем добавляет вторичный ключ и оценивает внутреннему Словарю.
Вам нужен ключевой класс для словаря, который реализует 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];
Я предложил бы небольшую вариацию на решение 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;
}
}
}
Я думаю, что это могло бы быть ближе к тому, что Вы ищете...
var data = new Dictionary<int, Dictionary<bool, int>>();
Как насчет того, чтобы использовать регулярный Словарь с некоторой структурой Кортежа как ключ?
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...
}
}
Я предложил бы, чтобы Вы создали маленький пользовательский класс, выставляющий bool и международные свойства, и переопределили его GetHashCode, и Равняется методам, затем используйте это в качестве ключа.
Посмотрите, этот код работает отлично:
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 ());
По сути, вам нужно использовать встроенную хеш-таблицу. Если вы думаете о своем
вопрос, хеш-таблица с двумя ключами - это функция с двумя независимыми
переменных, и 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
}
}
}