Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Finding the difference between two arrays

Status
Not open for further replies.

ttomasko

Programmer
Aug 6, 2008
28
Hello,

I will have two arrays of numbers. One will always be a subset of the other. What I want to know is which numbers only appear in the major set and put them in an array:

var a = [1,2,3,4,5,6];
var b = [1,2,3,6];
//result I want: [4,5]

I have tried concatenating a and b and then looking for doubles. The next step would be to delete the doubles but I can't figure out how to do that. I've also tried for statements to iterate through both arrays to find numbers that are unique in a and then push them to a new array but that does not work either.

I don't expect anyone to write the code but if you could give me a pointer or two, that would help.

I've searched the web and this exact problem does not come up except when the arrays consist of strings. I could convert the numbers to strings and use replace() to delete the doubles, then turn the string back into numbers. But that seems so inelegant.

Thanks,
Tom
 
I don't get this.

In thread216-1492308, you asked how to ensure all elements in two arrays are the same. You got plenty of helpful responses.

In thread216-1521966, you asked how to delete duplicates from arrays. You got plenty of helpful responses.

In thread216-1592013, you also asked how to delete duplicates from arrays. You also got a working answer.

Now you want to find the unique items in an array.

Are you trying to do one single thing, but haven't worked out the best way of achieving it, and thus the multiple questions to test different theories out?

If so, why not just post the end goal rather than continue to post requests for help with similar things that you never seem to learn from?

If not, are you not able to glean enough information or logic from those previous 3 posts all of a similar ilk? If this is the case, do you need things described in a simpler manner?

I'm not trying to point a finger, put you down, or have a go... I'm genuinely interested in why you have 4 very similar requests.

Dan



Coedit Limited - Delivering standards compliant, accessible web solutions

Dan's Page [blue]@[/blue] Code Couch:
Code Couch Snippets & Info:
The Out Atheism Campaign
 
Dan,

They are similar problems, and posing the three I did in the past (one very recently) has helped me solve those problems.

They are probably similar because I am applying JavaScript to the InDesign object model. Almost all the objects are found in arrays. I am writing scripts that will search thru hundreds of pages of a document and find various errors, from typos to styles of formatting.

I have written almost 50 different scripts, many of them using the solutions to the problems I have presented here in a simplified form. In this particular instance I can get an aray of all discretionary hyphens and another array of all such hyphens at the end of a line. What I need to do is to delete all discretionary hyphens that are not at the end of a line. There is no way to search for such animals in InDesign. But because I can get two arrays of the index numbers of these hyphens, I just need a third array, one that is the result of substracting the smaller array (index numbers of hyphens at end of line) from all hyphens. Then I can delete them.

I'll keep plugging away because I know there is a simple solution, simpler than turning the arrays into strings and back into numbers. Hopefully I can get some hints here.

Tom

 
I've also tried for statements to iterate through both arrays to find numbers that are unique in a and then push them to a new array but that does not work either.

From your description, it should work. Can you show the code you made to do this?

Dan



Coedit Limited - Delivering standards compliant, accessible web solutions

Dan's Page [blue]@[/blue] Code Couch:
Code Couch Snippets & Info:
The Out Atheism Campaign
 
You could try using the indexOf method of the arrays to determine which numbers from one array are not in another array.

Code:
function My_array_compare(arr1,arr2){
 var not_in_a=new Array;
 var j=0; 
 for(var i=0; i<=a.length-1;i++){
  if(b.indexOf(a[i])==-1){
    not_in_a[j]=a[i];
    j++;
  }

 }

return not_in_a;
}

Using indexOf you can check whether a value exists in the array by asking for its index, if a value does not exist it will return a -1, if any other number is returned its a valid index and means the value exists in the array. So just loop through the larger array to find which ones are not present in the smaller one.

----------------------------------
Phil AKA Vacunita
----------------------------------
Ignorance is not necessarily Bliss, case in point:
Unknown has caused an Unknown Error on Unknown and must be shutdown to prevent damage to Unknown.
 
Dear Dan and Phil,

I'll work on this and report back. But things have intervened and it will take me a few days.

Tom
 
OK, I have solved it. Thanks Phil for the idea of using indexOf().

There is a problem however with using this method in the InDesign object model; it does not recognize its use with numbers, only strings.

So below I turn the two arrays of numbers into strings. I then iterate thru the major string to see what values do not appear in the subset and push those values into an array. Then I change that array of string values back into integers.

I did not know one can iterate thru a string as one does thru an array!

Let me know if you see any flaws in the ointment. Or is that flies?

Thanks,
Tom

var a = [1,2,3,4,5,6];//major set
var b = [1,3,4]; //subset
var c = []; //want 2,5,6
var cc =[]; //will be array of numbers, not string of missing numbers.
//turn a and b arrays into strings
var aa = a.join();
var bb = b.join();
//search thru aa string to see if any values there do not appear in bb string
for(var j = 0; aa.length > j; j++){
if(bb.indexOf(aa[j]) == -1){
c.push(aa[j]);
}//end if
}//end for j
for(var i = 0; c.length > i; i++){
cc.push(parseInt(c));
}//end for i
cc;
 
Whoops! There is a big bug in the ointment: Numbers larger than one digit. IndexOf looks at a number such as 20 and sees values of 2 and 0.

Sigh...too late at night to solve now.

Tom
 
Hi

Phil certainly referred to [tt]Array.indexOf()[/tt], while you are using [tt]String.indexOf()[/tt]. Their behavior is abit different.
JavaScript:
[b]var[/b] a [teal]=[/teal] [teal][[/teal][purple]1[/purple][teal],[/teal][purple]2[/purple][teal],[/teal][purple]3[/purple][teal],[/teal][purple]4[/purple][teal],[/teal][purple]5[/purple][teal],[/teal][purple]6[/purple][teal]];[/teal][gray]//major set[/gray]
[b]var[/b] b [teal]=[/teal] [teal][[/teal][purple]1[/purple][teal],[/teal][purple]3[/purple][teal],[/teal][purple]4[/purple][teal]];[/teal] [gray]//subset[/gray]
[b]var[/b] c [teal]=[/teal] [teal][];[/teal] [gray]//want 2,5,6[/gray]
[gray]//search thru a array to see if any values there do not appear in b array[/gray]
[b]for[/b] [teal]([/teal][b]var[/b] j [teal]=[/teal] [purple]0[/purple][teal];[/teal] [highlight]a[/highlight][teal].[/teal]length [teal]>[/teal] j[teal];[/teal] j[teal]++)[/teal] [teal]{[/teal]
    [b]if[/b] [teal]([/teal][highlight]b[/highlight][teal].[/teal][COLOR=darkgoldenrod]indexOf[/color][teal]([/teal][highlight]a[/highlight][teal][[/teal]j[teal]])[/teal] [teal]==[/teal] [teal]-[/teal][purple]1[/purple][teal])[/teal] [teal]{[/teal]
        c[teal].[/teal][COLOR=darkgoldenrod]push[/color][teal]([/teal][highlight]a[/highlight][teal][[/teal]j[teal]]);[/teal]
    [teal]}[/teal][gray]//end if[/gray]
[teal]}[/teal][gray]//end for j[/gray]
c[teal];[/teal]
Note that [tt]Array.indexOf()[/tt] appeared in JavaScript 1.6, released in November 2005. So the code will not work in browsers older than that.

Next time please post your code between [tt][ignore]
Code:
[/ignore][/tt] and [tt][ignore]
[/ignore][/tt] TGML tags.

Feherke.
 
Feherke,

You didn't catch what I said. I am not working in a browser. I am applying JavaScript to an Adobe product. Further, the indexOf method does not work on arrays in InDesign, at least not the CS3 version. So I have to turn one of the arrays into a string, the one I will be apply the indexOf to. My mistake was turning them both into strings. If I turn the major array--the one with all of the numbers--into an array of strings rather than number values I achieve what I want.

The below code works with any number of more than one digit and the numbers do not have to be in order, which is the case for what I will be applying this script for.

Tom

Code:
var a = [1,20,200,3,2,64,5,16];
var aa = [];
var b = [1,3,4];
var c = []; //want 20,200,2,64,5,16
var cc =[]; //will be array of numbers not strings
//turn  a into array of strings and b  into a string
for(var k = 0; a.length > k; k++){
	aa.push(a[k]+"");
	}//end for k
var bb = b.join();
//search thru aa array to see if any values there do not appear in bb string
for(var j = 0; aa.length > j; j++){
	if(bb.indexOf(aa[j]) == -1){
		c.push(aa[j]);
		}//end if
	}//end for j
for(var i = 0; c.length > i; i++){
	cc.push(parseInt(c[i]));
	}//end for j
cc;
 
Feherke,

You didn't catch what I said. I am not working in a browser. I am applying JavaScript to an Adobe product. Further, the indexOf method does not work on arrays in InDesign, at least not the CS3 version. So I have to turn one of the arrays into a string, the one I will apply the indexOf to. My mistake was turning them both into strings. If I turn the major array--the one with all of the numbers--into an array of strings rather than number values I achieve what I want.

The below code works with any number of more than one digit and the numbers do not have to be in order, which is the case for what I will be applying this script for.

Tom

Code:
var a = [1,20,200,3,2,64,5,16];
var aa = [];
var b = [1,3,4];
var c = []; //want 20,200,2,64,5,16
var cc =[]; //will be array of numbers not strings
//turn  a into array of strings and b  into a string
for(var k = 0; a.length > k; k++){
	aa.push(a[k]+"");
	}//end for k
var bb = b.join();
//search thru aa array to see if any values there do not appear in bb string
for(var j = 0; aa.length > j; j++){
	if(bb.indexOf(aa[j]) == -1){
		c.push(aa[j]);
		}//end if
	}//end for j
for(var i = 0; c.length > i; i++){
	cc.push(parseInt(c[i]));
	}//end for j
cc;
 
Hi

Oops, I indeed missed that detail.

Anyway, please give up with the stringification idea. Unless you [tt]join()[/tt] the elements with a separator, that approach will lead to no success. ( Try to change [tt]var b [teal]=[/teal] [teal][[/teal][purple]1[/purple][teal],[/teal][purple]3[highlight]3[/highlight][/purple][teal],[/teal][purple]4[/purple][teal]];[/teal][/tt] and you will not have 3 in the difference array. )

If you have no [tt]indexOf()[/tt] method, then remember that JavaScript is prototype-base. So execute this first, then my previous code should work :
Code:
Array[teal].[/teal][b]prototype[/b][teal].[/teal]indexOf2[teal]=[/teal][b]function[/b] [teal]([/teal]what[teal])[/teal] [teal]{[/teal]
  [b]for[/b] [teal]([/teal][b]var[/b] i[teal]=[/teal][purple]0[/purple][teal];[/teal]i[teal]<[/teal][b]this[/b][teal].[/teal]length[teal];[/teal]i[teal]++)[/teal] [b]if[/b] [teal]([/teal][b]this[/b][teal][[/teal]i[teal]]==[/teal]what[teal])[/teal] [b]return[/b] i[teal];[/teal]
  [b]return[/b] [teal]-[/teal][purple]1[/purple][teal];[/teal]
[teal]}[/teal]
If not even that works in that environment :
Code:
[b]var[/b] a [teal]=[/teal] [teal][[/teal][purple]1[/purple][teal],[/teal][purple]2[/purple][teal],[/teal][purple]3[/purple][teal],[/teal][purple]4[/purple][teal],[/teal][purple]5[/purple][teal],[/teal][purple]6[/purple][teal]];[/teal][gray]//major set[/gray]
[b]var[/b] b [teal]=[/teal] [teal][[/teal][purple]1[/purple][teal],[/teal][purple]3[/purple][teal],[/teal][purple]4[/purple][teal]];[/teal] [gray]//subset[/gray]
[b]var[/b] c [teal]=[/teal] [teal][];[/teal] [gray]//want 2,5,6[/gray]
[gray]//search thru a array to see if any values there do not appear in b array[/gray]
[b]for[/b] [teal]([/teal][b]var[/b] j [teal]=[/teal] [purple]0[/purple][teal];[/teal] a[teal].[/teal]length [teal]>[/teal] j[teal];[/teal] j[teal]++)[/teal] [teal]{[/teal]
    [b]var[/b] found[teal]=[/teal][b]false[/b][teal];[/teal]
    [b]for[/b] [teal]([/teal][b]var[/b] i [teal]=[/teal] [purple]0[/purple][teal];[/teal] b[teal].[/teal]length [teal]>[/teal] i[teal];[/teal] i[teal]++)[/teal]
        [b]if[/b] [teal]([/teal]b[teal][[/teal]i[teal]]==[/teal]a[teal][[/teal]j[teal]])[/teal] [teal]{[/teal]
            found[teal]=[/teal][b]true[/b][teal];[/teal]
            [b]break[/b][teal];[/teal]
        [teal]}[/teal]
    [b]if[/b] [teal](![/teal]found[teal])[/teal] [teal]{[/teal]
        c[teal].[/teal][COLOR=darkgoldenrod]push[/color][teal]([/teal]a[teal][[/teal]j[teal]]);[/teal]
    [teal]}[/teal][gray]//end if[/gray]
[teal]}[/teal][gray]//end for j[/gray]
c[teal];[/teal]

Feherke.
 
Feherke,

I tested out [1,33,4] against [1]. The difference array is [33,4]. I tried other permutations and always get what I am looking for.

Maybe I did not make clear in my first note that opened this discussion that of the two arrays, the smaller one is always a subset of the other. The larger array is composed of the index numbers of all discretionary hyphens in a document. The smaller array is of those such hyphens that appear at the end of a line. I need an array of the index numbers of the hyphens that are inside lines of text so that I can delete them all, leaving only the end hyphens.

You suggest not using join() unless I add a separator. By leaving it blank the separator is a comma. The script only says look for a string with the value in aa[j], so it skips over any separator.

I've never written a prototype. I'll have to experiment with that. Thanks for writing one that applies to this specific problem.

Tom
 
feherke said:
var a = [1,2,3,4,5,6];//major set
var b = [1,3,4]; //subset
var c = []; //want 2,5,6
//search thru a array to see if any values there do not appear in b array
for (var j = 0; a.length > j; j++) {
var found=false;
for (var i = 0; b.length > i; i++)
if (b==a[j]) {
found=true;
break;
}
if (!found) {
c.push(a[j]);
}//end if
}//end for j


I came to the same code after tinkering a while, and before actually noticing your post.
I think this is pretty much the only way to do it, if the other methods don't work.


----------------------------------
Phil AKA Vacunita
----------------------------------
Ignorance is not necessarily Bliss, case in point:
Unknown has caused an Unknown Error on Unknown and must be shutdown to prevent damage to Unknown.
 
Hi

Tom said:
Maybe I did not make clear in my first note that opened this discussion that of the two arrays, the smaller one is always a subset of the other.
I noticed that, but after I saw your sample data :
Tom said:
Code:
var a = [1,20,200,3,2,64,5,16];
var b = [1,3,[highlight]4[/highlight]];
I supposed the "subset" was just bad wording as your array b is not subset of array a.

I do not want to challenge your patience, so I will show you only one more thing.
If you set the two arrays like this :
Code:
[b]var[/b] a [teal]=[/teal] [teal][[/teal][purple]1[/purple][teal],[/teal][purple]20[/purple][teal],[/teal][purple]200[/purple][teal],[/teal][purple]3[/purple][teal],[/teal][purple]2[/purple][teal],[/teal][purple]64[/purple][teal],[/teal][purple]5[/purple][teal],[/teal][purple]16[/purple][teal]];[/teal]
[b]var[/b] b [teal]=[/teal] [teal][[/teal][purple]1[/purple][teal],[/teal][purple]3[/purple][teal],[/teal][purple]20[/purple][teal]];[/teal]
The result should be [200,[highlight]2[/highlight],64,5,16], but your code gives [200,64,5,16].

Feherke.
 
Feherke,

No, you did not challenge my patience. This is how to learn.

You are right that the coding I used will sometimes fail. The missing 2 in this case has an index other than -1 so it doesn't get pushed to the new array.

Your code fits the bill and is a lot simplier. I tried it with various numbers.

I do have one question though. Would it make any difference if (!found) is changed to (found == false)?

Tom
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top