ISMEMBER() modified result desired

조회 수: 9 (최근 30일)
dpb
dpb 2019년 1월 19일
편집: dpb 2019년 1월 21일
[lia,locb]=ismember(A,B);
returns the first/last matching location in B of the elements in A that occur in B depending on which optional parameters one chooses. That's fine for many cases, but...
If it is desired to do a 1:1 matching of elements in A to their corresponding mates in B, a modified behavior would be a desirable option if there are repeated elements -- locB could return the next match after the previous for those elements that may not be unique in either array.
This can be done in a loop, of course, by making a search for each element in A in turn, either keeping an indexing variable as to last location for each element previously located or, conversely, marking the location in B with a missing value or somesuch.
That's the problem, the question is --
Is there some function which already does this that I'm not aware of/can't find or a "more cleverer" way to make the match?
  댓글 수: 5
Jan
Jan 2019년 1월 21일
What about a small example?
A = [1, 2, 3, 1, 2, 3];
B = [2, 2, 2, 3, 3];
Is the wanted output this:
lia = [0, 1, 1, 0, 1, 1] % as logical
locb = [0, 1, 4, 0, 2, 5]
% ^ ^ would be 1 and 4 for standard ISMEMBER
dpb
dpb 2019년 1월 21일
Yes, that's the idea...

댓글을 달려면 로그인하십시오.

답변 (2개)

Jan
Jan 2019년 1월 21일
편집: Jan 2019년 1월 21일
Do you mean something like this:
function [lia, locb] = ismemberNext(A, B)
lia = false(size(A));
locb = zeros(size(A));
for iA = 1:numel(A)
match = (A(iA) == B);
if any(match)
lia(iA) = true;
index = find(match, 1);
locb(iA) = index;
B(index) = NaN; % Mask first match for following calls
end
end
end
  댓글 수: 2
dpb
dpb 2019년 1월 21일
That's ok w/o the tolerance problem. I'd written (hadn't posted; didn't want to taint the pool first :) )
nG=numel(g); % number of gifts (formula values)
locV=zeros(size(g)); % preallocate lookup location
inV=zeros(size(g)); % preallocate lookup location
vmatch=zeros(size(g)); % matched values cleared
datematch=nat(size(g)); % and the monthy/yr associated
for j=1:nG % find & pair up matching formula values
[inV(j),locV(j)]=ismembertol(g(j),v,'DataScale',0.01);
if inV(j)
vmatch(j)=v(locV(j));
datematch(j)=MT_AU.Date(o(locV(j))); % MMMYY for the formula gift
v(locV(j))=nan;
end
end
vfail=v(isfinite(v)); % retrieve those not matched
The 0.01 tolerance is owing this particular dataset happens to be financial and from a spreadsheet in which there is rounding error in some returned values. One could wrap the find arguments inside a round call.
The datematch array is the corresponding auxiliary "timestamp" variable, v is the dollar value try to match to the g value between two sets of entries that should match but don't always..
It doesn't seem possible to do without the basic loop over the elements in the first and you used the same 'trick' to hide the already found element
The overall problem is a set of entries were made into a number of spreadsheets over a period of a number of years while a corresponding set of comments of which entry correlated to a given one of those entries. The problem is there are a few for which comments weren't entred and/or there were other accounting entries besides new contributions that may have been composite entries that don't match any particular single other entry. For tracking purposes have stripped the entries in the comments (the g array) and the task is to match the known v entries and then isolate the remainder. There's then another independent way with the value and the timestamp to identify which of those is which to finish the task.
dpb
dpb 2019년 1월 21일
for iA = 1:numel(A)
match = (A(iA) == B);
if any(match)
lia(iA) = true;
index = find(match, 1);
...
Slight optimization, maybe -- may as well just find the location first as have to convert the logical array anyway...
for iA = 1:numel(A)
index = find(A(iA) == B, 1);
if ~isempty(index)
lia(iA) = true;
...

댓글을 달려면 로그인하십시오.


Guillaume
Guillaume 2019년 1월 21일
Maybe I misunderstood the problem, but ismembertol already has the option to return all matching indices in B:
[found, where] = ismembertol(A, B, 'OutputAllIndices', true)
  댓글 수: 3
Guillaume
Guillaume 2019년 1월 21일
Are the A that match the same set of B exactly identical? If so, then it's easily solved. If there's a small tolerance on the As as well, then I'll have to think about it.
dpb
dpb 2019년 1월 21일
편집: dpb 2019년 1월 21일
Not necessarily identical, no...I have no way to know a priori which are those elements that contain the rounding discrepancies.
I was considering that I could just go ahead and round the Excel values when read the spreadsheet...that would certainly be faster and probably then makes the need for ismembertol go away...excepting ismember doesn't have the optional output...Catch-22! :)
It seems to me since TMW went this far, there might as well be the 'OutputMatchedIndices' option as well and imo if they're going to add a feature like this to one of the family member functions, it should go in all when it is first introduced, not create yet more uniqueness in interfaces than already exists.
In the end when I'm past the time crunch I'll see about crafting/submitting an enhancment request.
ADDENDUM
On reflection, I guess it would be possible to write
[inA,locB]=ismembertol(round(A,2), round(B,2), 'OutputAllIndices', true);
which _should_ then make the match identical...

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Matrix Indexing에 대해 자세히 알아보기

제품

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by