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 Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Removing an element from array 1

Status
Not open for further replies.

perln00b

Programmer
Oct 4, 2005
21
US
Support I have two arrays, and each of them doesn't have repeat elements. And compare the first array to the second one, if element repeats in 2nd array, the element has to be removed from the 1st one. i.e.
###################################################
@arry1 = ("1", "2", "3");
@arry2 = ("9", "10", "1");
###################################################

So, "1" is the common element for both arrays, but I only need to remove it from the 1st array.

Does anyone have any idea to handle this?

Thanks,
Lucas
 
You need to create a hash from the second with the values from your array as the keys and then you can walk through your first array using the hash to see if any of the values exist. If they do you can delete them.
Do you need anyone to show you how to do it?


Trojan.
 
Trojan,

I am appricated if you have a chance to show me how to do it.
And I did try to use array itself to handle it, but I got "Use of uninitialized value in string/print". Here is my code:
###########################################################
@arry1 = ("1", "2", "3");
@arry2 = ("9", "10", "1");
$size = @arry1;

for($i=0; $i<$size; $i++)
{
foreach $element (@arry2)
{
if ($arry1[$i] eq $element)
{
delete $arry1[$i];
splice(@arry1, $i, 1);
}
}
}
print "New array: \n";
foreach $a (@arry1)
{
print $a;
}
####################################################
It did print the result, but with error(see above).

Thanks,
Lucas
 
The problem with your solution is that the number of operations that your code does is a multiple of the length of the first array against the length of the second.
If your arrays were both 256 elements long then your code would have to do 256*266=65535 operations.
If you did as I suggested then you would need one pass to store array 2 as a hash (256) PLUS one pass of first array (256) and so you would do a total of 256+256=512 operations.
As you can see 512 operations is quite a bit better than 65536 operations.
Have another go and see how you get on. Doing things yourself is the best way to learn. If you get stuck, there are many of us here to help.


Trojan.
 
or you could:-

Code:
[b]#!/usr/bin/perl[/b]

@arry1 = ("1", "2", "3");
@arry2 = ("9", "10", "1");

for ($x=0; $x<=$#arry2; $x++) {
  $arry2[$x] = 'removed' if (grep "$arry2[$x]" eq $_, @arry1);
}

print join("\n", @arry2);

... kind of thing


Kind Regards
Duncan
 
Trojan,

If creating a hash using element in arry1 as keys, how to assign the corresponding values, and how to compare those elements in arry2? Sorry, I am really a noob in perl.

Thanks,
Lucas
 
Duncan, the only problem with using grep like that is it iterates through the entire array @arry1 for every member or @arry2. I agree with Trojan, the hash method would probably be the best way to go.
 
duncdude,

In your case, this only deals with those arrys have the
same length, right?

Thanks,
lucas
 
could anyone please give me more hints about this?

thanks
lucas
 
lucas, Duncan's code works no matter how many elements are in each array, the only problem with it is it loops through one of the @arry1 for each member of @arry2. Which has the same drawback that Trojan pointed out with your code.

To get you started with Trojan's suggestion, a basic way to create a hash with keys from @arry2, you could use code similar to:
Code:
my %hash;
foreach (@arry2){
    $hash{$_} = 1;
}
That will yield a hash in which all the keys are the elements from @arry2, and all the values are 1.

For the next part, to see if the value '10' is in %hash (and by corollary @arry2) here's some sample code for you:
Code:
my $search = 10;
if ($hash{$search}) {
    print "$search is here!\n";
} else {
    print "$search is not here!\n";
}
That code, using the data sets you provided, would print '10 is here!' Does that help point you in the right direction?
 
rharsh, thank you so much for your help. when you assigned 1 as a value for a hash, can you assign other values as well?
Now, suppose, see below
#####################################################
@arry = ("peter", "smith", "john", "kelly");
foreach $person (@arry)
{
$group{$person} = 1;
}
#####################################################
is it possible to create reverse hash for this since the key
has the same value "1"?

thanks,
lucas
 
lucas, you can assign any scalar value you want as the value for a certain key. In this case, the value you're assigning is, for the most part, irrelevent as long as perl evaluates that value as true (i.e. you shouldn't use 0 or "".)

In your example, you cannot reverse the hash, you'd end up with one key and one value (which would be 1 and 'kelly'.)

Oh, and when you post code, take a look at the
Code:
 tag.
 
rharsh, I am appreciated for your help. Now I want to go back to my previous post about hash of hashes.
Code:
$statement = "select studentID, studentName, courseID from student_table";
if ($db -> Sql($statement))
{
 # ..doing error handling
}
while ($db -> FetchRow())
{
@fields = $db -> Data();
$tempids{$fields[1]}{$fields[0]}{$fields[1]} = 1;
$rev_tempids{$fields[1]}{$fields[1]}{$fields[0]} = 1;
$tempidstrings{$fields[1]}{$fields[0]} .= "$fields[1],";
}

studentID studentName courseID
========== ============ ==========
001 J. Lo E102
001 J. Lo M335
912 J. Lo M335
912 J. Lo Ph212
110 M. J.
112 D. J. Csc102

In MJ's case, the courseID is missing, how %tempids, %rev_tempids, and %tempidstrings effect? We have two students with same name, but different student ID, how the hashes handle this case. If I need to update some information such as a new courseID adding to the current student, or a new student data, how can I do the comparison.

Thanks, :)
Lucas
 
is it possible to create reverse hash for this since the key
has the same value "1"?

the keys in any given hash are unique. No two keys can be the same, such as:

Code:
%hash = (
   cat => black,
   cat => gray,
);

that will end up with cat = gray.

[quote]
In MJ's case, the courseID is missing, how %tempids, %rev_tempids, and %tempidstrings effect?  We have two students with same name, but different student ID, how the hashes handle this case. If I need to update some information such as a new courseID adding to the current student, or a new student data, how can I do the comparison.
[/quote]

The student ID is probably the unique identifier of the student, not the name. If you need to update a students record you have to use their ID number to find the correct student and the correct type of record (courseID or whatever).
 
Ok I think that is better idea to assign to the hash element with key the value of the first array the array index. Then you will have no problem to remove form the first array, the element which index is equal to the value of the hash which key is equal to the element of the second array.

Lucas you code doesn't work because you assign to $size @array. You should use $#size.



Corwin
 
Uf stupid Corwin
@size = $#array
@array is the number of elements in the array.
$#array is the last index of the array



Corwin
 
So the code:

foreach (0 .. $#arr1) {
$hash{$arr1[$_]} = $_;
}

foreach (0 .. $#arr2) {
if ($hash($#arr2)) {
splice(@array1, $_, 1);
}
}

You should check the syntax, because I am also new to Perl and programming. Also I am not 100% sure if you should stop using strict 'vars' while $hash{$arr1[$_]} = $_;


Corwin
 
Ok this should be the source:

#!/usr/bin/perl -w
use strict;

my %hash;
my @arr1 = qw/1 3 5/;
my @arr2 = qw/2 4 1/;

foreach (0 .. $#arr1) {
$hash{$arr1[$_]} = $_;
}

foreach (0 .. $#arr2) {
if (exists $hash{$arr2[$_]}) {
splice(@arr1, $hash{$arr2[$_]},1 );
}
}
print $_ foreach (@arr1);

The problem of this is that each splice changes the size of the array, so it could do only one true splice. So my question is: Is there way to remove the elements with only one func? They will be in some type of an array.

P.S Sorry for the 4 posts in a row.



Corwin
 
#!/usr/bin/perl -w
use strict;

my %hash;
my @arr1 = qw/1 3 5 7/;
my @arr2 = qw/2 4 1 7/;


foreach (0 .. $#arr1) {
$hash{$arr1[$_]} = $_;
}

foreach (0 .. $#arr2) {
if (exists $hash{$arr2[$_]}) {
@arr1[$hash{$arr2[$_]}] = undef;
}
}
foreach (@arr1) {
print $_ if defined;
}

PS Sorry for the 5 posts in a row :(

Corwin
 
one way to do what you are trying:

Code:
my @arr1 = qw(1 R 3 5 7 9 X 12 2 W 3);
my @arr2 = qw(2 5 4 9 1 X);
my @temp = ();
my %hash = ();

map {$hash{$_}++} @arr2;
for (@arr1) {
   exists $hash{$_} ? next : push @temp,$_;
}
@arr1 = @temp;
print "@arr1"
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top