How to get indices of a specific value in a tensor in tensorflow-js? - tensorflow.js

For example, If I have a 2D tensor of [[1,3],[2,1]], how can I get indices of the value 1? (It should return [[0,0],[1,1]]).
I took a look into tf.where but the API is complicated and I don't think that would solve the problem for me

You can achieve this using tf.whereAsync.
Just create a mask which checks if the values in the input Tensor are of the value 1 and turn them into boolean values.
Mask:
"Tensor
[[true , false],
[false, true ]]"
tf.whereAsync() returns the coordinates of true elements of the condition which in this case come from the mask.
(async function getData() {
const x = tf.tensor2d([[1, 3], [2, 1]])
const mask = x.equal([1]).asType('bool');
const coords = await tf.whereAsync(mask);
coords.print();
}());
Input:
"Tensor
[[1, 3],
[2, 1]]"
Output:
"Tensor
[[0, 0],
[1, 1]]"

Related

Checking if any element in one array exists in another

I am trying to create a filtering system for some items by checking if the selected items exist in the presented values.
So my selectable array can range from 0 to 6, and each item contains an array of Ints that it is associated with:
let items = [
Item(cat: [1, 2, 3]),
Item(cat: [0, 6]),
Item(cat: []),
Item(cat: [0, 1])
]
I wanted to create a function that would check if any of the cat values were in the selected Ints:
#Published var filteredCats: [Int] = []
func filterByInt(array: [Item]) -> [Item] {
let output = array.filter({
guard let cats = $0.cats else { return true }
for cat in cats {
return filteredCats.contains(cat)
}
})
return output
}
But I'm having issue with the above since it returns in the loop on the first iteration, so if I was searching for 1 in the above items then Item(cat: [0, 1]) exits at false as the first looped check is 0==1.
Essentially I want to be able to do the following (in expanded terms):
let filter = [0, 3, 4]
let items = [
[1, 2, 3],
[2, 3],
[],
[5, 6, 7]
]
items.contains(filter) // --> return the arrays
Sorry if this is basic but I've been trying to find a good solution.
Checking uniqueness is where a Set can help
struct Item {
var cat: Set<Int>
}
let items = [
Item(cat: [1, 2, 3]),
Item(cat: [0, 6]),
Item(cat: []),
Item(cat: [0, 1])
]
let wanted: Set<Int> = [0, 3, 4]
let filtered = items.filter { !$0.cat.isDisjoint(with: wanted) }
I'd suggest someSatisfy (or any in Kotlin):
We can utilize allSatisfy with double negations (one for allSatisfy, the other for contains) for that:
struct Item: CustomDebugStringConvertible {
let cat: [Int]
var debugDescription: String {
"[" + cat.map { String($0) }.joined(separator: ", ") + "]"
}
}
func filterByInt(items: [Item], filter: [Int]) -> [Item] {
// Early return might make sense if the filter is empty.
// guard !filter.isEmpty else { return items }
items.filter { item in
!filter.allSatisfy {
filterItem in !item.cat.contains(filterItem)
}
}
}
let filter = [0, 3, 4]
let items: [Item] = [
.init(cat: [1, 2, 3]),
.init(cat: [2, 3]),
.init(cat: []),
.init(cat: [5, 6, 7])
]
print(filterByInt(items: items, filter: filter))
// [[1, 2, 3], [2, 3]]
print(filterByInt(items: items, filter: [5]))
// [[5, 6, 7]]
print(filterByInt(items: items, filter: []))
// []

ruby return array of values that exist in every nested array

I want to build a ruby function that finds the in-common elements of ALL nested arrays. For instance, given the following arrays, this is the answer it would come up with...
[[1, 2, 3], [1, 2], [2]]
=> [2]
[[1, 2, 3], [1, 2, 4]]
=> [1, 2]
I could do,
arr = [[1, 2, 3], [1, 2], [2]]
arr[0] & arr[1] & arr[2]
=> [2]
But not sure how to make that operation dynamic.
You're looking for the Enumerable#reduce (aka #inject) method. This performs aggregate calculations over an enumerable like an array. If you don't pass it an initial value, it will use the first element of the collection as the initial value.
arr.reduce { |a, b| a & b } # => [2]
And there's a convenient shorthand for this type of expression:
[[1, 2, 3], [1, 2], [2]].reduce(:&) # => [2]
[[1, 2, 3], [1, 2, 4]].reduce(:&) # => [1, 2]
[[1], [2]].reduce(:&) # => []
[].reduce(:&) # => nil

Best way to replace nils from array with elements of another array

I have two arrays:
a = [nil, 1, nil]
b = [4, 5, 6]
And i want to replace nil elements from first array with related elements from second array:
[4, 1, 6]
What is the best way to do it?
You can use zip and the || operator to do it:
result = a.zip(b).map{ |x,y| x || y }
If you want to replace exactly nil, but not false elements:
a.map.with_index { |e, i| e.nil? ? b[i] : e }
# => [4, 1, 6]
You can use
a.zip(b).map(&:compact).map(&:first) #=> [4, 1, 6]
Steps:
a.zip(b)
#=> [[nil, 4], [1, 5], [nil, 6]]
a.zip(b).map(&:compact)
#=> [[4], [1, 5], [6]]
a.zip(b).map(&:compact).map(&:first)
#=> [4, 1, 6]
By virtue of Array#compact this approach removes nil elements only from the zipped pairs i.e. false elements are not removed.
Another way is by using a block when creating this new array like so:
a = [nil, 1, nil]
b = [4, 5, 6]
Array.new(a.size) { |i| a[i].nil? ? b[i] : a[i] }
#=> [4, 1, 6]
Still another variant:
a.zip(b).map{|a, b| [*a, *b].first}
# => [4, 1, 6]
This distinguishes nil from false, as expected. But note that you cannot use this with elements that are broken by to_a, such as hashes.

Removing the smaller sets of values from an array of arrays in Swift

Given an array that consists of arrays containing integers.
[[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]]
What would be the preferred way in Swift to remove the arrays that contains a smaller number of elements with a certain value and keep only the larger arrays containing that value.
The result from the input above would be
[[5], [7], [2, 2, 2], [3, 3]]
Use a [Int: [Int]] dictionary to keep track of the largest array for the value specified by the key.
let arrays = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]]
var largest = [Int: [Int]]()
for arr in arrays {
// Get the first value from the array
if let first = arr.first {
// current is the count for that key already in dictionary largest
// If the key isn't found, the nil coalescing operator ?? will
// return the default count of 0.
let current = largest[first]?.count ?? 0
// If our new array has a larger count, put it in the dictionary
if arr.count > current {
largest[first] = arr
}
}
}
// Convert the dictionary's values to an array for the final answer.
let result = Array(largest.values)
print(result) // [[5], [7], [2, 2, 2], [3, 3]]
This same logic can be used with reduce to provide the result in one line:
let result = arrays.reduce([Int: [Int]]()) { var d = $0; guard let f = $1.first else { return d }; d[f] = d[f]?.count > $1.count ? d[f] : $1; return d }.map { $1 }
Alternate Version
This version uses a [Int: Int] dictionary to just keep the counts of the largest array found for each key, and then reconstructs the arrays at the end using an array constructor.
let arrays = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]]
var counts = [Int: Int]()
for arr in arrays {
if let first = arr.first {
counts[first] = max(counts[first] ?? 0, arr.count)
}
}
let result = counts.map { [Int](count: $1, repeatedValue: $0) }
print(result) // [[5], [7], [2, 2, 2], [3, 3]]
This same logic can be used with reduce to provide the result in one line:
let result = arrays.reduce([Int: Int]()) { var d = $0; guard let f = $1.first else { return d }; d[f] = max(d[f] ?? 0, $1.count); return d }.map { [Int](count: $1, repeatedValue: $0) }
I was just about to write up my answer when I saw that vacawama had responded with something very similar. Decided to come back to it though just because it's an interesting problem to play around with. So my alternative is almost certainly much slower that vacawama's solutions and doesn't preserve the order, but I thought it was interesting as an example of the alternatives that you have for solving problems like this in Swift.
var items = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]]
let reduced = items.sort({
let lhs = $0.first, rhs = $1.first
return lhs == rhs ? $0.count > $1.count : lhs < rhs
}).reduce( [[Int]]()) { (res, items) in
return res.last?.last != items.last ? res + [items] : res
}
print(reduced) // [[2, 2, 2], [3, 3], [5], [7]]
Or if you'd rather cram all that on a single line:
var items = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]]
let reduced = items.sort({ let lhs = $0.first, rhs = $1.first; return lhs == rhs ? $0.count > $1.count : lhs < rhs }).reduce([[Int]]()) { $0.last?.last != $1.last ? $0 + [$1] : $0 }
print(reduced) // [[2, 2, 2], [3, 3], [5], [7]]
Just an alternative using forEach:
let arrays = [[2], [2, 2], [5], [7], [2, 2, 2], [3, 3], [3]]
var largest: [Int: [Int]] = [:]
arrays.forEach({
guard let first = $0.first else { return }
largest[first] = [Int](count: max($0.count,largest[first]?.count ?? 0), repeatedValue: first)
})
Array(largest.values) // [[5], [7], [2, 2, 2], [3, 3]]

Grails - sort collection by an element AND an array

Is there a "groovy" way to sort a collection by a first parameter, and if the first parameter repeats in two or more elements sort it by a second parameter (the second parameter being an array) ?
Example:
edited (Lenght of the sub array is variable):
[1, [1,2,3]]
[1, [4,6]]
[2, [1,2,3,4,5]]
[3, [1,2,3]]
[3, [1,2,4,5]]
Thanks in advance
You can use the .sort if you want to build up a custom sort:
def lis = []
lis << [3, [1,2,4]]
lis << [1, [1,2,3]]
lis << [3, [1,2,3]]
lis << [1, [4,5,6]]
lis << [2, [1,2,3]]
lis.sort{a,b->
if(a[0]==b[0])
{
def aArray = a[1]
def bArray = b[1]
for(int i=0;i<aArray.size();i++)
{
if(bArray[i])
{
if(aArray[i]!=bArray[i])
{
return aArray[i]<=>bArray[i]
}
}
else
{
return 1
}
}
return 0
}
else
return a[0]<=>b[0]
}
lis.each{x->
println x
}
I didn't really deal well with the case that the lists are different lengths you could improve on that for your apps needs.
Have a look at the following gist of tim yates.
It shows a way how to sort a list with multiple comparators.
For your example:
Collection.metaClass.sort = { boolean mutate, Closure... closures ->
delegate.sort( mutate ) { a, b ->
closures.findResult { c -> c( a ) <=> c( b ) ?: null }
}
}
def list = [[3, [1,2,3]],
[1, [4,5,6]],
[2, [1,2,3]],
[1, [1,2,3]],
[3, [1,2,4]]]
assert list.sort(false, {it[0]}, {it[1][0]}, {it[1][1]}, {it[1][2]}) == [[1, [1,2,3]],
[1, [4,5,6]],
[2, [1,2,3]],
[3, [1,2,3]],
[3, [1,2,4]]]
Hopes that helps ...

Resources