Как транслировать операцию набора для массива наборов в Julia?

#julia

#джулия

Вопрос:

Я пытаюсь выполнить операции набора между заданным набором y и всеми элементами в некотором массиве наборов X следующим образом:

 X=Array{Set}([Set([1,2,1]), Set([4,6,8 ]), Set([4,5])]) 
y=Set{Int16}([2,8,4])
z=broadcast(intersect, y, X)

println(z)
 

Что дает мне пустые множества вместо наборов с одиночными y элементами, для моего примера.

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

1. Запись Array{Set}(...) вообще не очень хорошая идея. Это превращает массив в вектор с абстрактным типом элемента. [Set([1,2,1]), Set([4,6,8 ]), Set([4,5])] имеет тип Array{Set{Int64},1} , но вы превращаете его в абстрактный eltype Array{Set,1} . Это может привести к снижению производительности.

2. @DNF, спасибо за ваш комментарий. Я новичок в Джулии, поэтому был бы признателен, если бы вы порекомендовали альтернативный эффективный подход.

3. Просто напишите X = [Set([1,2,1]), Set([4,6,8 ]), Set([4,5])] , и пусть Джулия сама разбирается с типами. Также немного лучше писать Set(Int16[2,8,4]) , чем Set{Int16}([2,8,4]) потому, что последний сначала создает вектор Int64 , в который затем превращается Int16 , в то время как первый непосредственно создает Int16 s . Но мне интересно, почему вы используете Int16 здесь.

4. Спасибо @DNF. Нет причин использовать Int16, я только пытался быть корректным, указав тип, но теперь я знаю некоторые дополнительные детали благодаря вашему комментарию.

Ответ №1:

Вы должны защитить y себя от повторения. Обычно вы получаете сообщение об ошибке, но, к сожалению y , имеет три элемента, а также вектор X . Давайте создадим вектор большего размера, чтобы увидеть проблему:

 julia> X=Array{Set}([Set([1,2,1]), Set([4,6,8 ]), Set([4,5]), Set([7])])
4-element Array{Set,1}:
 Set([2, 1])
 Set([4, 8, 6])
 Set([4, 5])
 Set([7])

julia> y=Set{Int16}([2,8,4])
Set{Int16} with 3 elements:
  4
  2
  8

julia> z=broadcast(intersect, y, X)
ERROR: DimensionMismatch("arrays could not be broadcast to a common size; got a dimension with lengths 3 and 4")
 

Как это решить — обернуть y в 0-мерный контейнер Ref(y) примерно так:

 julia> z=broadcast(intersect, Ref(y), X)
4-element Array{Set{Int16},1}:
 Set([2])
 Set([4, 8])
 Set([4])
 Set()
 

или, что эквивалентно, просто напишите:

 julia> z=intersect.(Ref(y), X)
4-element Array{Set{Int16},1}:
 Set([2])
 Set([4, 8])
 Set([4])
 Set()
 

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

1. Спасибо @Bogumil Kaminski, это решило мой вопрос.