Comparing different sized arrays in Matlab - arrays

I need to compare two different arrays in Matlab. It's going to be used for a Yahtzee game. If I have an array that contains [1 2 3 4] and an array that contains [1 2 3 4 5], how do I check if the first array is contained within the second array. I just need to know a T/F result, not anything about which elements are missing, etc.

ismember will do it. For example:
x = [1 2 3 4]
y = [1 2 3 4 5]
all(ismember(x,y))
You can also use setdiff. For example:
isempty(setdiff(x,y))

another option,
all(intersect(x,y)==x)
but ismember is probably more efficient....

Related

Julia: Flattening array of array/tuples

In Julia vec reshapes multidimensional arrays into one-dimension arrays.
However it doesn't work for arrays of arrays or arrays of tuples.
A part from using array comprehension, is there another way to flatten arrays of arrays/tuples? Or arrays of arrays/tuples of arrays/tuples? Or ...
Iterators.flatten(x) creates a generator that iterates over each element of x. It can handle some of the cases you describe, eg
julia> collect(Iterators.flatten([(1,2,3),[4,5],6]))
6-element Array{Any,1}:
1
2
3
4
5
6
If you have arrays of arrays of arrays and tuples, you should probably reconsider your data structure because it doesn't sound type stable. However, you can use multiple calls to flatten, eg
julia> collect(Iterators.flatten([(1,2,[3,3,3,3]),[4,5],6]))
6-element Array{Any,1}:
1
2
[3, 3, 3, 3]
4
5
6
julia> collect(Iterators.flatten(Iterators.flatten([(1,2,[3,3,3,3]),[4,5],6])))
9-element Array{Any,1}:
1
2
3
3
3
3
4
5
6
Note how all of my example return an Array{Any,1}. That is a bad sign for performance, because it means the compiler could not determine a single concrete type for the elements of the output array. I chose these example because the way I read your question it sounded like you may have type unstable containers already.
In order to flatten an array of arrays, you can simply use vcat() like this:
julia> A = [[1,2,3],[4,5], [6,7]]
Vector{Int64}[3]
Int64[3]
Int64[2]
Int64[2]
julia> flat = vcat(A...)
Int64[7]
1
2
3
4
5
6
7
The simplest way is to apply the ellipsis ... twice.
A = [[1,2,3],[4,5], [6,7]]
flat = [(A...)...]
println(flat)
The output would be
[1, 2, 3, 4, 5, 6, 7].
If you use VectorOfArray from RecursiveArrayTools.jl, it uses the indexing fallback to provide convert(Array,A) for a VectorOfArray A.
julia> using RecursiveArrayTools
julia> A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
3-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
julia> VA = VectorOfArray(A)
3-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
First of it acts as a lazy wrapper for doing the indexing without conversion:
julia> VA[1,3]
7
Note that columns are the separate arrays so that way it's still "column-major" (i.e. efficient to index down columns). But then it has a straight conversion:
julia> convert(Array,VA)
3×3 Array{Int64,2}:
1 4 7
2 5 8
3 6 9
The other way to handle this conversion is to do something like hcat(A...), but that's slow if you have a lot of arrays you're splatting!
Now, you may think: what about writing a function that pre-allocates the matrix, then loops through and fills it? That's almost what convert on the VectorOfArray works, except the fallback that convert uses here utilizes Tim Holy's Cartesian machinery. At one point, I wrote that function:
function vecvec_to_mat(vecvec)
mat = Matrix{eltype(eltype(vecvec))}(length(vecvec),length(vecvec[1]))
for i in 1:length(vecvec)
mat[i,:] .= vecvec[i]
end
mat
end
but I have since gotten rid of it because the fallback was much faster. So, YMMV but that's a few ways to solve your problem.
for Julia 0.7x:
for Arrays:
flat(arr::Array) = mapreduce(x -> isa(x, Array) ? flat(x) : x,
append!, arr,init=[])
for Tuples:
flat(arr::Tuple) = mapreduce(x -> isa(x, Tuple) ? flat(x) : x,
append!, arr,init=[])
Works for arbitrary depth.
see: https://rosettacode.org/wiki/Flatten_a_list#Julia
Code for Array/Tuple:
function flatten(arr)
rst = Any[]
grep(v) = for x in v
if isa(x, Tuple) || isa(x, Array)
grep(x)
else push!(rst, x) end
end
grep(arr)
rst
end

How to index a Julia array

I am having trouble understanding what seems like an inconsistent behavior in Julia.
X = reshape(1:100, 10, 10)
b = [1 5 9]
X[2, :][b] # returns the correct array
X[2, :][1 5 9] # throws an error
Can someone explain why using the variable b works to index an array but not when I write the index myself?
Since x = X[2,:] is just a vector, we can simplify the example to just talking about indexing behavior on vectors.
x[v] where v is a collection of integers returns the subset of x. Thus x[(1,5,9)], or x[[1,5,9]] is thus using that getindex(x::Vector,i::AbstractArray) dispatch.
Note that x[[1 5 9]] works because v = [1 5 9] makes v a row vector. That's valid syntax, but x[1 5 9] just isn't even valid Julia syntax. That syntax means something else:
v = Float64[1 5 9]
returns a row vector with element type Float64.
I have figured out a solution.
Rather than write X[2, :][1 5 9] I should have written x[2, :][[1 5 9]]
I believe this makes sense when we imagine indexing on two dimensions the second time. This makes it possible to write more complicate indices, like X[2:4, :][[1 3],[1 3]]

Removing elements from a cell array in MATLAB

I have a cell array as shown below:
a = {[1 2 3] [5 3 6] [9 1 3]};
Now I want to remove the 1s from every array in a that contains 1 so that the output is as shown
a = {[2 3] [5 3 6] [9 3]};
I know the indices of arrays in cell array 'a' which contain 1. This can be done using for loop and a temporary variable, but this is taking a lot of time (I want to perform the operation on a cell array of size something like 1x100000. The one above is just for an example)
I want to know if there is any direct method that can do this quickly.
Pretty much anything is going to be slow with that large of a cell array. You could try to do this with cellfun but it's not necessarily guaranteed to be any faster than a for loop.
a = cellfun(#(x)x(x ~= 1), a, 'UniformOutput', false);
% a{1} =
% 2 3
% a{2} =
% 5 3 6
% a{3} =
% 9 3
As already commented by Suever, because you are using a cell array and it is a dynamic container, you don't have a choice but to iterate through each cell if you want to modify the contents. Just to be self-contained, here is the for loop approach to do things:
for ii = 1 : numel(a)
a{ii} = a{ii}(a{ii} ~= 1);
end
This may be faster as it doesn't undergo the overhead of cellfun. The code above accesses the vector in each cell and extracts out those values that are not equal to 1 and overwrites the corresponding cell with this new vector.
Using your example:
a = {[1 2 3] [5 3 6] [9 1 3]};
We get:
>> format compact; celldisp(a)
a{1} =
2 3
a{2} =
5 3 6
a{3} =
9 3
This example shows how to remove data from individual cells, and how to delete entire cells from a cell array. To run the code in this example, create a 3-by-3 cell array:
C = {1, 2, 3; 4, 5, 6; 7, 8, 9};
Delete the contents of a particular cell by assigning an empty array to the cell, using curly braces for content indexing, {}:
C{2,2} = []
This code returns
C =
[1] [2] [3]
[4] [] [6]
[7] [8] [9]
Delete sets of cells using standard array indexing with smooth parentheses, (). For example, this command
C(2,:) = []
removes the second row of C:
`
C =
[1] [2] [3]
[7] [8] [9]`

MATLAB: two S and V vectors, vector S is a subset of the vector V, how to extract vector (V-S) with a simple command [duplicate]

I know this is simple but am having a hard time finding the right function for this. I have a vector a = [1 2 3 4] and another vector b = [1 2 6 8]. I want to return all of the elements in a that aren't in b. In this case, it would be [3 4]. How do you do this?
did you try with setdiff?
c = setdiff(a,b)

How to find repeated cell vectors in matlab?

I have n different length cell vectors, call it c{i}, i=1,2,...,n.
I wanna find those c{i} which equal with others, for example:
c{1}=[1 2 3 4 5 6]; c{2}=[1 3 5 7]; c{3}=[2 4 6 8];
c{4}=[1 4 6]; c{5}=[3 7]; c{6}=[2 4 6 8]; c{7}=[1 3 5 7];
I hope I can find [2 4 6 8] and [1 3 5 7] with a simple way instead of using two loops.
Thanks!
You can do it with unique. You need to convert vectors to strings, because unique works with cell arrays of strings but not with cell arrays of numeric vectors. After unique, you can count how many strings (vector) are repeated with histc, and them some indexing lets you retrieve the corresponding vectors:
strcell = cellfun(#(e) num2str(e), c, 'uniformoutput', 0); %// convert to strings
[~, ii, jj] = unique(strcell); %// apply unique. Second and third outputs needed
ind = find(histc(jj,min(jj)-.5:max(jj)+.2)>1); %// which appear more than once
result = c(ii(ind)); %// indexing to obtain corresponding original vectors

Resources