Как сравнить значения из одного SortedDictionary, чтобы добавить их в новый SortedDictionary?

#c# #keyvaluepair #sorteddictionary

#c# #keyvaluepair #sorteddictionary

Вопрос:

У меня есть 2 SortedDictionary «mainsd» amp;amp; «valuesd». Условия, которые я пытаюсь запрограммировать, гласят следующее:

Если сумма значений 2 ключей выше MaxValue в «mainsd» больше или равна сумме значений 2 ключей ниже MaxValue в «mainsd»

Затем: добавьте 2 пары KeyValuePairs над MaxValue в «valuesd»

Еще: добавьте 2 пары KeyValuePairs ниже MaxValue в «valuesd»

Продолжайте добавлять до valuesd .Values.Sum() достигает 50% от основного значения.Values.Sum()

Другими словами, сравните 2 значения выше и ниже максимального, в зависимости от того, что больше, добавьте к значениюd и расширяйте, пока мы не достигнем 50% от общего значения mainsd.

 "mainsd" contains the following
{
   Key , Value
500.10 , 500
500.09 , 1000
500.08 , 2000
500.07 , 3000
500.06 , 4500 --------> Step 6: 4500 5500 > 5000 4000 (Add 500.05 amp; 500.06 to "valuesd")
500.05 , 5500
500.04 , 6000 --------> Step 5: 6000 7000 > 5000 4000 (Add 500.03 amp; 500.04 to "valuesd")
500.03 , 7000
500.02 , 8500 --------> Step 2: 8500 9500 > 9000 8000 (Add 500.01amp;500.02 to "valuesd")
500.01 , 9500
500.00 , 10000 -------> Step 1: Max Value (Add to "valuesd") 
499.99 , 9000
499.98 , 8000 --------> Step 3: 9000 8000 > 7000 6000 (Add 499.99 amp; 499.98 to "valuesd")
499.97 , 7500
499.96 , 6500 --------> Step 4: 6500 7500 > 6000 7000 (Add 499.97 amp; 499.96 to "valuesd")
499.95 , 5000
499.94 , 4000--------> Step 7: 4000 3500 > 3000 2000 (Add 499.94 amp; 499.95 to "valuesd")
499.93 , 3500
499.92 , 2500
499.91 , 1500
499.90 , 550
}
Keep going until 50% is reached.
  

Вот что я получил, но это не дает ожидаемых результатов.

 mainsd = new SortedDictionary<double,int>(); 
valuesd = new SortedDictionary<double,int>();

if (!valuesd.ContainsKey(mainsd.Values.Max()))
{
 valuesd.Clear();
 valuesd.Add(mainsd.FirstOrDefault(x => x.Value == (mainsd.Values.Max()).Key),(mainsd.Values.Max()))
}

var vhi = valuesd.Keys.First();
var vlo = valuesd.Keys.Last();
double u1 = vhi 0.01;
double u2 = vhi 0.02;
double d1 = vlo 0.01;
double d2 = vlo 0.02;

if (mainsd.ContainsKey(u1) amp;amp; mainsd.ContainsKey(u2))
{
 int up1 = mainsd[u1];
 int up2 = mainsd[u2];
}
if (mainsd.ContainsKey(d1) amp;amp; mainsd.ContainsKey(d2))
{
 int dn1 = mainsd[d1];
 int dn2 = mainsd[d2];
}

if (valuesd.Values.Sum()/mainsd.Values.Sum() < 0.5)
{
 if (up1 up2>=dn1 dn2 amp;amp; !valuesd.ContainsKey(u1) amp;amp; !valuesd.ContainsKey(u2))
 {
  valuesd.Add(u1,up1);
  valuesd.Add(u2,up2);
 }
 else if (up1 up2<dn1 dn2 amp;amp; !valuesd.ContainsKey(l1) amp;amp; !valuesd.ContainsKey(l2))
 {
  valuesd.Add(d1,dn1);
  valuesd.Add(d2,dn2);
 }
}
Print("Hi=" valuesd.Keys.First() "Lo=" valuesd.Keys.Last());
  

Если МАКСИМАЛЬНОЕ значение было 500.

Вывод: Hi = 500.01 Lo = 499.99

Любая помощь приветствуется.

Комментарии:

1. Можете ли вы опубликовать свой фактический код? Это не компилируется и, похоже, отсутствуют фигурные скобки и некоторые точки с запятой.

2. Я обновил свой код, чтобы он точно соответствовал тому, что у меня есть на данный момент.

3. Условия не добавляют идентифицированную KeyValuePair из «mainsd» в «valuesd»

4. Почему вы используете «double» в качестве типа данных для ключей? Поскольку извлечение значений из ключей в этот момент приведет к получению ‘int’?

5. Я использую double для ключей, потому что входящие данные поступают с шагом 0,01.

Ответ №1:

Вот незавершенная попытка с использованием LINQ получить две последовательности, одну для перечисления вперед (начиная с максимального элемента) и одну для перечисления назад. После этого нелегко продолжить работу с LINQ, потому что две последовательности должны быть перечислены параллельно сложным образом, поэтому я пошел с циклом while.

 var mainsd = new SortedDictionary<double, int>()
{
    {500.10, 500}, {500.09, 1000}, {500.08, 2000}, {500.07, 3000},
    {500.06, 4500}, {500.05, 5500}, {500.04, 6000}, {500.03, 7000},
    {500.02, 8500}, {500.01, 9500}, {500.00, 10000}, {499.99, 9000},
    {499.98, 8000}, {499.97, 7500}, {499.96, 6500}, {499.95, 5000},
    {499.94, 4000}, {499.93, 3500}, {499.92, 2500}, {499.91, 1500},
    {499.90, 550},
};
var maxValue = mainsd.Max(e => e.Value);
var maxItemKey = mainsd.First(e => e.Value == maxValue).Key;
var forward = mainsd.SkipWhile(e => e.Key <= maxItemKey).ToArray();
var backward = mainsd.TakeWhile(e => e.Key < maxItemKey).Reverse().ToArray();
int i1 = 0;
int i2 = 0;
while (true)
{
    var sum1 = i1 < forward.Length - 1 ? forward[i1].Value   forward[i1   1].Value : 0;
    var sum2 = i2 < backward.Length - 1 ? backward[i2].Value   backward[i2   1].Value : 0;
    if (sum1 == 0 amp;amp; sum2 == 0) break;
    if (sum1 >= sum2)
    {
        Console.WriteLine($"Forward:  {sum1}, Keys: {forward[i1].Key}, {forward[i1   1].Key}");
        i1  = 2;
    }
    else
    {
        Console.WriteLine($"Backward: {sum2}, Keys: {backward[i2   1].Key}, {backward[i2].Key}");
        i2  = 2;
    }
}
  

Вывод:

 Forward:  18000, Keys: 500,01, 500,02
Backward: 17000, Keys: 499,98, 499,99
Backward: 14000, Keys: 499,96, 499,97
Forward:  13000, Keys: 500,03, 500,04
Forward:  10000, Keys: 500,05, 500,06
Backward: 9000, Keys: 499,94, 499,95
Backward: 6000, Keys: 499,92, 499,93
Forward:  5000, Keys: 500,07, 500,08
Backward: 2050, Keys: 499,9, 499,91
Forward:  1500, Keys: 500,09, 500,1
  

Обновление: вот чего не хватает для завершения программы. Перед входом в while цикл мы создаем valuesd словарь:

 var valuesd = new SortedDictionary<double, int>();
  

Внутри while цикла есть два случая. Если sum1 >= sum2 мы добавим две записи из списка пересылки:

 valuesd.Add(forward[i1].Key, forward[i1].Value);
valuesd.Add(forward[i1   1].Key, forward[i1   1].Value);
  

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

 valuesd.Add(backward[i2].Key, backward[i2].Value);
valuesd.Add(backward[i2   1].Key, backward[i2   1].Value);
  

В конце while цикла мы проверяем, достигли ли мы цели в 50%. Если мы это сделаем, пришло время выйти из цикла с помощью вызова break .

 if (valuesd.Values.Sum() >= mainsd.Values.Sum() * 50 / 100) break;
  

После выхода из цикла valuesd словарь заполняется необходимыми записями.

Комментарии:

1. Спасибо! Пара вопросов, где бы я поставил условие, чтобы прекратить добавление вперед и назад при достижении 50%? Кроме того, как бы я добавил ключи, которые вы создали в своем выводе, в «valuesd»?

2. Вы можете создать переменную вне цикла while, которая будет содержать текущую сумму, а внутри цикла вы увеличите эту переменную либо на sum1, либо на sum2 . Затем (все еще внутри цикла) вы можете проверить, стала ли текущая сумма больше половины от общей суммы. Итоговое значение должно быть предварительно вычислено перед входом в цикл, вероятно, с использованием LINQ (метод Sum ). Значение d может быть заполнено с помощью метода Add .

3. Большое вам спасибо, мистер Зулиас

4. Мистер Зулиас, я работаю над этим кодом с апреля, и я записал все, кроме проверки, если текущая сумма больше половины общей суммы… Все, что я пытаюсь, приводит к сбою системы… Не могли бы вы показать мне, что вы подразумеваете под своим комментарием от 20 апреля? Очень признателен

5. Большое вам спасибо! Теперь он работает отлично. Ценю всю вашу помощь.