Страницы: 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
Согласие есть продукт при полном непротивлении сторон
 
Коллеги, мне этот эффект знаком:
Код
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.
Владимир
 
Sanja, что-то я никогда не встречал , чтоб так, "по наглому", можно было обратится для записи.
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
чтоб так, "по наглому", можно было обратится для записи.
С Михаилом неинтересно - слишком быстро думает.

В #8 выражение da("Key1") возвращает переменную типа variant, являющуюся массивом. Мы изменяем эту переменную, но объекту da про это ничего не известно.
Владимир
 
Цитата
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.05.2019 17:00:24
Владимир
 
sokol92, Владимир, приветствую. да это я видел. Про Exists написал только по причине того что нечего ошибку теребонькать и это не относится к основному вопросу.
По вопросам из тем форума, личку не читаю.
 
Цитата
Ігор Гончаренко написал: массив из словаря передать переменной, изметить значение, затолкать массив обратно в словарь
Игорь, я собственно так и делаю (строки кода с 10 по 14 в стартовом сообщении).
Просто хотелось убедиться что прямого доступа для изменения элементов массива, который сам является элементом словаря, НЕТ.
Все, всем большое спасибо!
Согласие есть продукт при полном непротивлении сторон
 
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.05.2019 20:35:35
«Бритва Оккама» или «Принцип Калашникова»?
 
Off
Сейчас пришло в голову, что эту задачу я решал, когда писал программу Life (по ссылке выкладывал все исходники на репозитории, кому интересно). Там так же в контейнере std::unordered_map (хранит пары ключ-значение с уникальными ключами) хранил байтовый массив, точнее указатели, и доступ был к элементам байтового массива через указатель, и даже больше - работал с отдельными битами в каждом байте. Все это через прямую адресацию к памяти. Полный доступ к памяти, конечно, сильный инструмент.
Sanja, переходите на С++ :) Свои dll для Excel, скорость и защита.
P.S. будет с кем живительные выстрелы в ногу пообсуждать :)
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
Sanja написал:
Да, было бы не лишним. Если можно, то в той, моей, теме, по ссылке выше
Класс ArrayContainer. В данной версии позволяет поместить внутри "контейнера" копию массива, ссылку на внешний массив или переместить внешний массив внутрь контейнера. Экземпляр класса можно поместить в любой com-объект, и изменять массив, нахдящийся в экземпляре класса, не выходя за рамки одного строкового выражения в коде. Как-то длинно получиолось, сам чуть не запутался ) Используются возможности vba-класса, а также встроенного типа, а если точнее класса Variant, который является частью не только vba, но и Com архитектуры в целом, но в то же время его история возникновения тесно связана с VBA/VB, кстати..
Пример использования
Скрытый текст
Изменено: testuser - 01.06.2024 08:33:19 (Устранил баг взникающий при повторном добавлении массива в "контейнер")
 
Отлично! Спасибо testuser!
Тема приобрела законченный вид  :)
Согласие есть продукт при полном непротивлении сторон
 
Дальше обсуждаем тут
Согласие есть продукт при полном непротивлении сторон
Страницы: 1
Читают тему
Наверх