Skip to main content
Added a new method
Source Link
NonDairyNeutrino
  • 7.9k
  • 1
  • 14
  • 31

Method 1: Calculate all products

We can calculate all the products of the terms via KroneckerProduct and simply find where the positive ones are, and then get the right indices.

Clear[vec, indset]
vec = {5, 2, -2, -4, 3};
indset = {-1, 1};

KroneckerProduct[indset, vec] (*"Multiply" the two lists*);
Position[%, _?Positive] (*Find where the positive results are*) (*Can be improved to not use pattern matching*);
{indset[[#1]], #2} & @@@ % (*Map the indset indices to the actual values*)

{{-1, 3}, {-1, 4}, {1, 1}, {1, 2}, {1, 5}}

Method 2: Pairing Like-Sign Terms

We can also use the fact that a positive product can only result from the multiplication of like-signed terms. Therefore each of the indices of the positive entries in the non-index list necessarily have to be accompanied by each of the positive entries in the index list. Similarly for the negatives of each.

GroupBy[
  Transpose@{vec, Range@Length@vec} (*{{element, index},..}*), 
  (*Group by the sign of the element*) Sign@*First -> Last (*Take the index*)
]
(*<|1 -> {1, 2, 5}, -1 -> {3, 4}|>*)
GroupBy[indset, Sign]
(*<|-1 -> {-1}, 1 -> {1}|>*)
Tuples[{%[#], %%[#]}] & /@ {-1, 1} // Catenate (*Every like-sign term pairs with every other like-sign term*)

{{-1, 3}, {-1, 4}, {1, 1}, {1, 2}, {1, 5}}

Clear[vec, indset]
vec = {5, 2, -2, -4, 3};
indset = {-1, 1};

KroneckerProduct[indset, vec] (*"Multiply" the two lists*);
Position[%, _?Positive] (*Find where the positive results are*) (*Can be improved to not use pattern matching*);
{indset[[#1]], #2} & @@@ % (*Map the indset indices to the actual values*)

{{-1, 3}, {-1, 4}, {1, 1}, {1, 2}, {1, 5}}

Method 1: Calculate all products

We can calculate all the products of the terms via KroneckerProduct and simply find where the positive ones are, and then get the right indices.

vec = {5, 2, -2, -4, 3};
indset = {-1, 1};

KroneckerProduct[indset, vec] (*"Multiply" the two lists*);
Position[%, _?Positive] (*Find where the positive results are*);
{indset[[#1]], #2} & @@@ % (*Map the indset indices to the actual values*)

{{-1, 3}, {-1, 4}, {1, 1}, {1, 2}, {1, 5}}

Method 2: Pairing Like-Sign Terms

We can also use the fact that a positive product can only result from the multiplication of like-signed terms. Therefore each of the indices of the positive entries in the non-index list necessarily have to be accompanied by each of the positive entries in the index list. Similarly for the negatives of each.

GroupBy[
  Transpose@{vec, Range@Length@vec} (*{{element, index},..}*), 
  (*Group by the sign of the element*) Sign@*First -> Last (*Take the index*)
]
(*<|1 -> {1, 2, 5}, -1 -> {3, 4}|>*)
GroupBy[indset, Sign]
(*<|-1 -> {-1}, 1 -> {1}|>*)
Tuples[{%[#], %%[#]}] & /@ {-1, 1} // Catenate (*Every like-sign term pairs with every other like-sign term*)

{{-1, 3}, {-1, 4}, {1, 1}, {1, 2}, {1, 5}}

Source Link
NonDairyNeutrino
  • 7.9k
  • 1
  • 14
  • 31

Clear[vec, indset]
vec = {5, 2, -2, -4, 3};
indset = {-1, 1};

KroneckerProduct[indset, vec] (*"Multiply" the two lists*);
Position[%, _?Positive] (*Find where the positive results are*) (*Can be improved to not use pattern matching*);
{indset[[#1]], #2} & @@@ % (*Map the indset indices to the actual values*)

{{-1, 3}, {-1, 4}, {1, 1}, {1, 2}, {1, 5}}