Изменить сечения для одного элемента - PullRequest
1 голос
/ 25 апреля 2020

Я играю с примером на https://code.kx.com/q/ref/amend/#cross -секциях

$ q
KDB+ 3.6 2019.04.02 Copyright (C) 1993-2019 Kx Systems
q)d:((1 2 3;4 5 6 7);(8 9;10;11 12);(13 14;15 16 17 18;19 20))
q)i:(2 0; 0 1 0)
q)y:(100 200 300; 400 500 600)
q)r:.[d; i; ,; y]

Все работает нормально, если только я не попытаюсь сослаться на один элемент d [1 ; 1]:

q)i:(1 0; 0 1 0)
q)r:.[d; i; ,; y]
'type
  [0]  r:.[d; i; ,; y]

Но если я использую объединение , для списков и только для одного элемента, оно работает так, как предполагалось:

q)10,200
10 200
q)10,((),200)
10 200

Так почему операция исправления прерывается на этом простое объединение?

Upd:

Еще один пример:

q)@[(1; 2; 3);1;,;10]
'type
  [0]  @[(1; 2; 3);1;,;10]
       ^

но это нормально, если один из списков использования:

q)@[(1; (),2; 3);1;,;10]
1
2 10
3

Ответы [ 2 ]

2 голосов
/ 26 апреля 2020

Ответ заключается в изучении данных, которые вы извлекаете для присоединения, здесь оператор -3! - ваш друг, который поможет выявить фактическую структуру через несколько слоев набора

q)d:((1 2 3;4 5 6 7);(8 9;10;11 12);(13 14;15 16 17 18;19 20))
q)i1:(2 0; 0 1 0)
q)i2:(1 0; 0 1 0)
q)y:(100 200 300; 400 500 600)
q)-3!r1:.[d; i1]
"((13 14;15 16 17 18;13 14);(1 2 3;4 5 6 7;1 2 3))"
q)q){type each x} each .[d; i1]
7 7 7
7 7 7
q)-3!r2:.[d; i2]
"((8 9;10;8 9);(1 2 3;4 5 6 7;1 2 3))"
q){type each x} each .[d; i2]
7 -7 7
7 7  7

Нет, здесь мы можем видеть что в первом случае каждый элемент r1 представляет собой список списков, но для r2 первый элемент представляет собой 2 списка длинных с атомом c long 10.

Из документации по сечению

Форма у равна 2 3, такая же форма, как у сечения, выбранного с помощью d. i

т. е. Shape должен соответствовать количеству и типам, тип каждого элемента y равен 7h, что должно соответствовать типу каждого выбора из d.

По существу, когда вы используете операторы поправок , и @, он будет ожидать соответствия, так как использует поправку на месте. a:1;a,:1 2 3 также не удастся.

Мы можем подтвердить это другими вашими примерами

q)type @[(1; (),2; 3);1]
7h

Изменение этого примера для настройки первого элемента

q)@[(1; (),2; 3);0;,;10]
'type

Причина, по которой просто используется оператор , поскольку 10,((),200) не вызвало каких-либо ошибок, это потому, что вы используете его за пределами корректирующих перегрузок, в рамках корректирующей перегрузки , ожидает, что будет работать с соответствующей формой. При непосредственном использовании он может продвигать и корректировать форму.

2 голосов
/ 26 апреля 2020

Единственное объяснение, которое я могу предложить, - это когда kdb + пытается использовать изменение на месте (также известное как назначение через оператора ), когда это возможно.

Например, это работает :

q)l:(13 14;15 16 17 18;19 20)
q)l[1],:200
q)l
13 14
15 16 17 18 200
19 20

Но это не так:

q)l:(8 9;10;11 12)
q)l[1],:200
'type
[0]  l[1],:200
       ^

Последнее не удается, поскольку kdb не может заменить вектор 10 200 на atom 10 - изменение типов - это не то, что должно делать изменение на месте.

Если вы использовали свою собственную функцию {x,y} вместо оператора плюс второе выражение из вашего примера будет работать так же, как и ожидалось, потому что kdb заменит существующих значений возвращаемыми значениями функции (которая, в отличие от встроенного ,, является черным ящиком до сих пор) что касается kdb):

q)i:(1 0; 0 1 0)
q)r:.[d; i; ,; y]
q).[d; ii; {x,y}; y]
(1 2 3 400 600;4 5 6 7 500)
(8 9 100 300;10 200;11 12)
(13 14;15 16 17 18;19 20)
...