1

Say I have the following code:

class Restaurant
{
    const FRUITS = 1;
    const VEGETABLES = 2;
    const MEET = 4;

    static public $data = [
        self::FRUITS     => ['apple', 'banana'],
        self::VEGETABLES => ['tomato', 'potato'],
        self::MEET       => ['beef', 'pig']
    ];

    public static function getSomething($byte)
    {
        // unknown logic for me
    }
}

Restaurant::getSomething(Restaurant::FRUITS | Restaurant::MEET);
// ['apple', 'banana', 'beef', 'pig']

I need to implement some logic which makes join operations based on bitwise operations.

What is the best way to do that?

3
  • I don't think there's any "elegant" solution. You'll have to manually test for the bits and merge the arrays. You should be able to use a loop. Commented Jan 14, 2015 at 14:05
  • Just as an aside, there is a spelling mistake, should be MEAT. Not MEET. Commented Jan 14, 2015 at 14:09
  • Michael, cause I want to pass flags to class dynamically and don't work with arrays outside Restaurant class. Commented Jan 14, 2015 at 14:10

2 Answers 2

4

Use ($byte & $bw) === $bw where $byte is whatever value you're testing with (eg. 3) and $bw is your bitwise value (eg. 1, 2 or 4) to check if bitwise values match.

Why does it work?

It's fairly simple. When we AND items, we're only using the bit values that are present in both values

$byte  = 3 = 0011
$bw    = 2 = 0010
AND'ed = 2 = 0010 (the same as $bw - $bw is included!)
               ^ 1 & 1 = 1
-----------------

$byte  = 5 = 0101
$bw    = 2 = 0010
AND'ed = 0 = 0000 (empty as the values do not match - $bw is NOT included)
               ^ 0 & 1 = 0

Code:

<?php

class Restaurant
{
    const FRUITS     = 1; // 0001
    const VEGETABLES = 2; // 0010
    const MEET       = 4; // 0100

    static public $data = [
        self::FRUITS     => ['apple', 'banana'],
        self::VEGETABLES => ['tomato', 'potato'],
        self::MEET       => ['beef', 'pig']
    ];

    public static function getSomething($byte)
    {
        // Start with an empty array
        $returnItems = array();

        // Loop through our bitwise values
        foreach (self::$data as $bw => $items) {

            // Is it included in $byte?
            if (($byte & $bw) === $bw) {

                // Then add the items in $items to $returnItems
                $returnItems = array_merge($returnItems, $items);
            }
        }

        // Return the items
        return $returnItems;
    }
}

Test:

$result = Restaurant::getSomething(Restaurant::FRUITS | Restaurant::MEET); // 5 - 0101

var_dump($result);

/*
    array(4) {
      [0]=>
      string(5) "apple"
      [1]=>
      string(6) "banana"
      [2]=>
      string(4) "beef"
      [3]=>
      string(3) "pig"
    }
*/

DEMO

Sign up to request clarification or add additional context in comments.

Comments

1

Nothing too fancy I'd say...

public static function getSomething($bitmask)
{
    $result = [];
    foreach(self::$data as $key => $value)
    {
        if(($key & $bitmask) !== 0)
        {
            $result = array_merge($result, $value);
        }
    }

    return $result;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.