Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Регистрация
Войти
 
Страницы: 1
RSS
Изменение элемента массива, являющегося элементом словаря
 
По мотивам ЭТОЙ темы.
Здравствуйте Уважаемые!
Давно хотел уточнить у Вас, дорогие друзья, такой вопрос.
Есть Словарь элементами которого являются Массивы
Как (и можно ли в принципе), напрямую, без передачи Массива в переменную, изменить какое нибудь его значение?
Прочитать единичное значение напрямую получается, а вот изменить никак.
Макрос складывает отдельные значения по ключу.
Может где-то в синтаксисе туплю...
Код
Private Sub CommandButton1_Click()
Dim x(), iArr(), newArr(), I&, J&
x = Range("A1:F4").Value
On Error Resume Next
With CreateObject("Scripting.Dictionary")
    For I = 1 To UBound(x)
        .Add x(I, 1), Application.Index(x, I, 0)
        If Err <> 0 Then
            'так работает
            iArr = .Item(x(I, 1))
            For J = 2 To UBound(iArr)
                iArr(J) = iArr(J) + x(I, J)
            Next
            .Item(x(I, 1)) = iArr
'            'необходимо увеличить каждый элемент массива на определенное значение
'            'прямое изменение элемента массива не работает
'            For J = 2 To UBound(.Item(x(I, 1)))
'                .Item(x(I, 1))(J) = .Item(x(I, 1))(J) + x(I, J)
'            Next
            Err.Clear
        End If
    Next
    ReDim newArr(1 To .Count, 0 To UBound(x, 2)): I = Empty
    For Each iKey In .Keys
        I = I + 1: newArr(I, 0) = I
        'простое обращение к элементу массива работает
        For J = 1 To UBound(.Item(iKey))
            newArr(I, J) = .Item(iKey)(J)
        Next
    Next
End With
Range("A16").Resize(UBound(newArr), UBound(newArr, 2) + 1) = newArr
End Sub
Согласие есть продукт при полном непротивлении сторон.
 
ОФФ.
Это Медведю (БМВ), если зайдет в тему.
Поздравляю!
ПВ.jpg (59.28 КБ)
Согласие есть продукт при полном непротивлении сторон.
 
пофлудим  раз уж Саня начал
присоединяюсь к поздравлениям и поздравляю сам себя в/ч2188 отдельный арктический погран отряд
Лень двигатель прогресса, доказано!!!
 
Цитата
Сергей написал: отдельный арктический погран отряд
Карелия forever! (2150 Суоярви, 2143 Калевала, Костомукша)
P/S/ Все, хана теме :D  
Изменено: Sanja - 28 Май 2019 14:37:48
Согласие есть продукт при полном непротивлении сторон.
 
Цитата
Sanja написал:
Все, хана теме
сам начал  :D  
Лень двигатель прогресса, доказано!!!
 
Попросим Юрия почистить лирические отступления
Согласие есть продукт при полном непротивлении сторон.
 
А я то думаю - с чего бы это у медведя фуражка появилась?
Цитата
Сергей написал:
отдельный арктический погран отряд
Всю жизнь считал, что в Арктике БЕЛЫЕ медведи. На аве белый медведь? Таких не берут в космонавты пограничники ))
 
Коллеги, поздравляю всех причастных! Мне этот эффект знаком:
Код
Sub test3()
  Dim da As Object
  Set da = CreateObject("Scripting.Dictionary")
  da("Key1") = Array(1)
  da("Key1")(0) = 2
  Debug.Print da("Key1")(0)
End Sub

Выдает 1.
Владимир
 
Цитата
sokol92 написал:
На аве белый медведь?
на аве ленивец в секрете сидит блюдёт границу
Лень двигатель прогресса, доказано!!!
 
Цитата
Sanja написал:
хана теме
ну не совсем:  2150 Суоярви, 4пз :-) . Сергей,  Поздравляю тоже.

Sanja, что-то я никогда не встречал , чтоб так, "по наглому", можно было обратится для записи.
 
Всех причастных с праздником! Мирного неба над головой.

Sanja, надо всё-таки было в Курилке "развивать" тему  :D
«Тот, кто несет фонарь, спотыкается чаще, чем тот, кто идет следом.»
Иоганн Пауль Фридрих Рихтер
 
Цитата
БМВ написал:
чтоб так, "по наглому", можно было обратится для записи.
С Михаилом неинтересно - слишком быстро думает.

В #8 выражение da("Key1") возвращает переменную типа variant, являющуюся массивом. Мы изменяем эту переменную, но объекту da про это ничего не известно.
Владимир
 
off
Цитата
Юрий М написал:
с чего бы это у медведя фуражка появилась
так в офис нельзя, тут дрэскод, вот разве на форуме поносить чуток. :-)
 
Цитата
Sanja написал:
Прочитать единичное значение напрямую получается, а вот изменить никак.
видимо, есть на то весомые причины при попытке изменить зачение элемента массива, никто об ошибке не пишет, но и не делает ничего!
массив из словаря передать переменной, изметить значение, затолкать массив обратно в словарь
Код
Sub Test()
  Dim ar, dc, i&
  Set dc = CreateObject("Scripting.Dictionary")
  ar = Array("A", "B", "Start")
  dc.Add "test", ar:           Debug.Print "1. " & dc("test")(2)
  dc("test")(2) = "In dc var": Debug.Print "2. " & dc("test")(2)
  ar = dc("test")
  ar(2) = "in external var"
  dc("test") = ar:             Debug.Print "3. " & dc("test")(2)
End Sub
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Sanja, но я б обработку ошибки (несмотря на то что она не решает основной вопрос) заменил бы на проверку Exists. код не сильно больше.
 
Цитата
БМВ написал:
она не решает основной вопрос
? См. #12
В строке 18 из #1 (не закомментированной) свойство  .Item(x(I, 1)) возвращает нам массив Variant/Variant(). Мы в этом возвращенном массиве (временная переменная?) меняем один из элементов. На массив, хранящийся в словаре, это действие не влияет.
Изменено: sokol92 - 28 Май 2019 17:00:24
Владимир
 
sokol92, Владимир, приветствую. да это я видел. Про Exists написал только по причине того что нечего ошибку теребонькать и это не относится к основному вопросу.
 
Цитата
Ігор Гончаренко написал: массив из словаря передать переменной, изметить значение, затолкать массив обратно в словарь
Игорь, я собственно так и делаю (строки кода с 10 по 14 в стартовом сообщении).
Просто хотелось убедиться что прямого доступа для изменения элементов массива, который сам является элементом словаря, НЕТ.
Все, всем большое спасибо!
Скоро пограничные сутки заканчиваются можно и коньячку 'потеребонькать' !
Ну, за ПВ!
Изменено: Sanja - 28 Май 2019 18:06:11
Согласие есть продукт при полном непротивлении сторон.
 
Успехов всем пограничникам!
Владимир
 
Sanja, как мог, порылся. Результаты выкладываю (не впечатляющие).
1. В первом тесте записал по выдаваемом словарем адресу - инфу (2), т.к. инфа не дошла до внутренностей библы, делаю вывод - данные отдаются по ByVal, залезть в библу не смогу.
2. Во втором тесте попробовал запихнуть весь массив, опять же не вышло (хотя в этом же тесте, обмен инфой между двумя массивами по указателю проходит нормально), из чего вывод - da("Key1") это не ссылка/указатель, а ByVal, которую нам выкладывает библа. В свои внутренности не пускает.
3. В третьем тесте можно хранить указатель/ссылку в библиотеке и работать с ним, как с обычным массивом...
Ах да... это VBA, а не С++

В итоге: прямого доступа к элементам коллекции - не нашел. Работа только через методы самой  библиотеки, с передачей информации по значению - ByVal.

Код
Private Declare PtrSafe Function VarPtrArray Lib "VBE7" Alias "VarPtr" (ByRef Var() As Any) As LongPtr
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Sub test1()
  Dim da As Object, y As Long
  Set da = CreateObject("Scripting.Dictionary")
  da("Key1") = Array(0&, 1&, 2&)
  y = 2& 'хотим 2
  CopyMemory ByVal VarPtr(da("Key1")(1)), ByVal VarPtr(y), 4&
  'похоже мы переписали память, которая ByVal
  Debug.Print da("Key1")(1)
End Sub

Sub test2()
  Dim da As Object, y
  Dim Arr1() As Long
  Dim Arr2() As Long
  ReDim Arr1(0 To 5)
  ReDim Arr2(0 To 5)
  Set da = CreateObject("Scripting.Dictionary")
  da("Key1") = Arr1
  
  'так можем, смотрим данные из второго массива
  Arr2(5) = 2
  CopyMemory ByVal VarPtrArray(Arr1), ByVal VarPtrArray(Arr2), 4 * 6
  Debug.Print Arr1(5)
  
  'не можем записать массив по адресу, который выдает словарь
  CopyMemory ByVal VarPtrArray(da("Key1")), ByVal VarPtrArray(Arr2), 4 * 6& 'здесь возникает ошибка
  Debug.Print da("Key1")(1)
End Sub

Sub test3()
  Dim da As Object, y, x
  Dim Arr1()
  Dim Arr2()
  ReDim Arr1(0 To 5)
  ReDim Arr2(0 To 5)
  Set da = CreateObject("Scripting.Dictionary")
  da("Key1") = VarPtrArray(Arr1)
' все! дальше извлечь данные по ссылке/указателю в VBA - не представляется работоспособным
  Debug.Print da("Key1")
End Sub


Парни, все что мог, за время, которое удалось выкроить.
Всех с Праздником!
Изменено: bedvit - 28 Май 2019 20:35:35
«Бритва Оккама» или «Принцип Калашникова»?
 
Off
bedvit,  20:00 прошло.  Все , праздник прошел , также как и прошли надежды на изменение массива в словаре без выгрузки и загрузки :-).
 
Off
БМВ, 20:00 - по-моему праздник в самом разгаре, вся ночь впереди! :-)
«Бритва Оккама» или «Принцип Калашникова»?
 
Про Мухтара не забудьте...
 
Off
Сейчас пришло в голову, что эту задачу я решал, когда писал программу Life (по ссылке выкладывал все исходники на репозитории, кому интересно). Там так же в контейнере std::unordered_map (хранит пары ключ-значение с уникальными ключами) хранил байтовый массив, точнее указатели, и доступ был к элементам байтового массива через указатель, и даже больше - работал с отдельными битами в каждом байте. Все это через прямую адресацию к памяти. Полный доступ к памяти, конечно, сильный инструмент.
Sanja, переходите на С++ :) Свои dll для Excel, скорость и защита.
P.S. будет с кем живительные выстрелы в ногу пообсуждать :)
«Бритва Оккама» или «Принцип Калашникова»?
Страницы: 1
Читают тему (гостей: 1)
Наверх