Page 1 of 1

Determining the intersection of an Associative array?

Posted: Mon Jun 30, 2003 3:13 pm
by tridude
I have a multi-dimensional array that contains lists (arrays) of userids that belong to a given group. For example:

Code: Select all

$useridsїgreen]ї0]=joe
$useridsїgreen]ї1]=sam
$useridsїgreen]ї2]=jim
$useridsїred]ї0]=joe
$useridsїblue]ї0]=joe
$useridsїblue]ї1]=jane
What I'm trying to do is compute the intersection of the individual arrays making up the larger, mult-dimensional array. In the sample above, the result would be joe, as joe is the only userid in the green, red, and blue groups. The multi-dimensional array is loaded by taking a set of groups checked by a user on a form and querying an LDAP server to get the members of the individual checked groups. If I can figure out this array intersection piece, I'll have a form that allows and administrator to check some groups on a form and produce a list of userids that are members of ALL the groups that were checked.

I've tried various incarnations of foreach loops and the array_intersect, array_values, and array_keys functions. At this point, I can verify that the LDAP query is loading the array correctly by using nested foreach loops to print the members of all the groups checked on the form.
However, the logic here is kicking me in the head and I'm starting to get dizzy.

Thanks in advance for saving my head.

Posted: Mon Jun 30, 2003 3:51 pm
by m@ndio
can I see your code?

Posted: Mon Jun 30, 2003 4:23 pm
by tridude
can I see your code?

Code: Select all

// Define the array of attributes to retrieve for each entry returned 
    // from the LDAP query
    $attrs = array("cn", "memberuid");

    // Query LDAP for each of the "checked" groups on the web form and
    // populate the $memberuids array with the results
    //
    // First we talk to LDAP and get our result...
    foreach ($_POSTї'display_groups'] as $checked_group) {
        $filter = "(cn=$checked_group)";
        $ldapsearch = ldap_list($ldapconn, $groupdn, $filter, $attrs);
        $result = ldap_first_entry($ldapconn, $ldapsearch);
        $values = ldap_get_values($ldapconn, $result, "memberuid");

        // Take the result and populate the array of memberuids for the group
        for ($i=0; $i<$values&#1111;"count"]; $i++) &#123;
            $memberuids&#1111;$checked_group]&#1111;$i] = $values&#1111;"$i"];
        &#125;

        // This code is only for testing that the $memberuids associative
        // array was loaded properly. It prints out the members of each
        // checked group.
        foreach($memberuids as $a) &#123;
            foreach ($a as $uid) &#123;
            print "$uid"."<br>";
            &#125;
        &#125;
So there you go. I'm thinking perhaps there might be a way to compute the intersection of the first two arrays, get the result, and compare it against the next array. We'll see how that works, though admittedly, it doesn't seem very efficient the more I think about it.

Posted: Mon Jun 30, 2003 4:27 pm
by m@ndio
Do you have a link to the file on the web so I can see what you are trying to do? it's still a bit unclear of what you want?

Posted: Mon Jun 30, 2003 4:36 pm
by pootergeist

Code: Select all

$groups = array('green','red','blue');
// could populate that within the db call
$count_groups = count($groups);

foreach($userids[$groups[0]] AS $var=>$value)
	{
	// iterate all values of first array dimension 
	$test_num = 0;
	for($g_count = 1; $g_count < $count_groups; $g_count++)
		{
		// test all other array dimensions for value - add one if found
		$test_num = (in_array($value, $userids[$groups[$g_count]])) ? $test_num+1 : $test_num;
		if($test_num == $count_groups)
			{
			// value appears in all groups
			echo $value. ' is in every group';
			}
		else
			{
			// kill for loop if value not found - more efficient
			$g_count += $count_groups;
			}
		}
	}
should work - flytyped though

Posted: Mon Jun 30, 2003 4:41 pm
by volka
I guess that's what http://www.php.net/array_intersect is all about ;)

Code: Select all

<?php
$userids = array(
		'green' => array('joe', 'sam', 'jim'),
		'red' => array('joe'),
		'blue' => array('joe', 'jane')
	);


$inter = array_intersect($userids['green'], $userids['red'], $userids['blue']);
print_r($inter);

// or even simpler and "open for new colors"...
$inter = call_user_func_array('array_intersect', $userids);
print_r($inter);
?>

Posted: Mon Jun 30, 2003 4:46 pm
by tridude
Sorry, but I have no link. Let me describe it better:

This is an administrative application for controlling access to various web-based resources. Access to these resources is controlled by membership in various groups. If your userid is in a group and that group is allowed access, then you in turn can access that resource.

From time to time management would like some reports on who has access to certain resources. By obtaining the list of members for a given group you can easily see who has acess to a given resource. The sales force would also like to know which products a customer currently has access to so that they may try to sell them additional products.

What I'm attempting to do is present a form to the management folks that lists each of the existing groups to which accounts can belong. Next to each group is a checkbox. If a user checks the box next to the group called "Monthly Reports", a list of userids who currently are members of the "Monthly Report" group is returned. If a sales person wants a list of all userids who currently have access to "Monthly Reports" and "Weekly Reports", he checks both of those boxes on the form and is returned a list of userids that are members of the "Monthly Reports" group AND the "Weekly Reports" group. Essentially, only users who belong to ALL of the groups checked on the form are returned.

Hopefully that makes sense.

Posted: Mon Jun 30, 2003 4:59 pm
by volka
where's this information stored?
A database?

Posted: Mon Jun 30, 2003 5:22 pm
by tridude
Userid information (contact info, passwords) and Group information is stored in LDAP. LDAP is used as the authentication system for access to various web-based resources (data files, reports, charts, etc.).

The sample code that you folks have provided works wonderfully, except that the arrays are created dynamically from the group or groups that get checked on the web form.

Posted: Mon Jun 30, 2003 5:55 pm
by volka
hm, only query those groups that are requested.
The call_userfunc_array approach should work anyway.
Or if you have to query all groups take a look at this example

Code: Select all

<html>
	<body>
<?php
$userids = array(
		'green' => array('joe', 'jane', 'sam', 'jim'),
		'red' => array('joe', 'jim'),
		'blue' => array('joe', 'jane')
	);

if(isset($_POST['groups']))
{
	$search = array();
	foreach($_POST['groups'] as $group)
	{
		if (isset($userids[$group]))
			$search[$group] = $userids[$group];
	}
	switch(count($search))
	{
		case 0:
			echo 'no groups selected';
			break;
		case 1:
			echo 'only one group selected<pre>'; print_r($search); echo '</pre>';
			break;
		default:
			echo '<pre>'; print_r(call_user_func_array('array_intersect', $search)); echo '</pre>';
	}	
}
?>
		<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
			<table>
<?php
	foreach($userids as $key=>$value)
		echo '<tr><td>', $key, '</td><td><input type="checkbox" name="groups[]" value="', urlencode($key),'"/></td></tr>';
?>
				<tr><td>&nbsp;</td><td><input type="submit" /></td></tr>		
			</table>
		</form>
	</body>
</html>