tags:

views:

93

answers:

4

Hi, I have the following code which currently limits the result into a couple of types (Banana, Orange or all):

function selectFromArray($prefix="", $productArray=array()) {
    if(!strlen($prefix)) return $productArray;
    return array_filter($productArray,
        create_function('$element', 
             'return (stripos($element[1],'.var_export($prefix, true).') === 0); '));
}
$setype = $_GET[stype];
$list = selectFromArray($setype, $list);
foreach($list as $r) 
{ 
$size2 = $r[2]; 
 echo "<tr>
        <td id=\"id\"><span id=\"non_sorting_header\">" .$r[0]. "</span></td>
        <td id=\"name\"><span id=\"non_sorting_header\">" .$r[1]. "</span></td>
        <td id=\"speed\"><span id=\"sorting_header\">" .kMGTB2($size2). "</span></td>
     <td id=\"download\"><span id=\"sorting_header\">" .$r[3]. " Gb<br />per month</span></td>
        <td id=\"contract\"><span id=\"sorting_header\">1<br />month</span></td>
        <td id=\"info\"><span id=\"non_sorting_header\">".$r[5]."</span></td>
        <td id=\"buy\"><span id=\"non_sorting_header\">&pound;".$r[4]."<br />".$r[6]."</span></td>
      </tr>"; 
}

$r[0] is the product type and $setype = $_GET[stype]; sets the product type.

I need to combine the code above with a way of limiting the results further by using $r[0] which is the id value in the array. The array is created from an XML query from another site - so I have no control over it, so its not just a case of removing the entries from the array.

For instance the array can have upto 50 different id's in it but I want to limit the ones displayed in the table to just 10 (1024,1045,1023 etc).

Please help this is doiung my head in!!!!

A: 

You can add a counter and break after 10 iterations have passed, since you cannot modify the query.

$ids = array(1043,1055,1078);
foreach($list as $r) 
{ 
    if (in_array($r[0], $ids))
    {
     $size2 = $r[2]; 
      echo "<tr>
             <td id=\"id\"><span id=\"non_sorting_header\">" .$r[0]. "</span></td>
             <td id=\"name\"><span id=\"non_sorting_header\">" .$r[1]. "</span></td>
             <td id=\"speed\"><span id=\"sorting_header\">" .kMGTB2($size2). "</span></td>
             <td id=\"download\"><span id=\"sorting_header\">" .$r[3]. " Gb<br />per month</span></td>
             <td id=\"contract\"><span id=\"sorting_header\">1<br />month</span></td>
             <td id=\"info\"><span id=\"non_sorting_header\">".$r[5]."</span></td>
             <td id=\"buy\"><span id=\"non_sorting_header\">&pound;".$r[4]."<br />".$r[6]."</span></td>
           </tr>"; 
    }
}

Edit:

I've assumed you want to limit the result to the first 10 ID's. Im not sure if you wanted to limit it to 10 specific ID's instead. Please clarify if that is the case

Edit 2: Accommodates specific ID's in a base array.

Ian Elliott
thanks, but wouldnt this just give the first 10 instead of me being able to select the required entries?
Yeah, the question was kind of vague in this sense, let me fix.
Ian Elliott
Yep it would be specific ID's
seems to clash with the other if statement:if(!strlen($prefix)) return $productArray; return array_filter($productArray, create_function('$element', 'return (stripos($element[1],'.var_export($prefix, true).') === 0); '));}
It can't clash, the function is called before the for loop even starts. If anything there's other missing functions that cause you to get an unexpected output, but with respect to what you posted my solution has the same behaviour, although it skips over some values while processing. The interactions are unchanged...
Ian Elliott
A: 

Could you create a second, temporary array, and loop through the elements of the first one - starting with the first object you want to display?

// Pseudo code, ignore minor errors :P
$array = array();

for ($i = 1023, $i > 1034, $i++){
    // Copy your array elements from $r to $temp;
}

foreach ($temp as $whatever) {
    // Print out $whatever
}

Would that do the trick? Obviously you'd change 1023 and 1034 to suit your values.

EvilChookie
A: 

You could create another filter function which lets you filter an array based on a specific key. I have done it with a foreach but you could use array_filter() and create_function() as you have in your other function.

function filterArrayByKeyInArray($array, $searchKey, $searchValues) {
    $result = array();
    foreach ($array as $key => $row) {
        if (in_array($row[$searchKey], $searchValues)) {
            $result[$key] = $row;
        }
    }
    return $result;
}

//snip
$list = selectFromArray($setype, $list);
$list = filterArrayByKeyInArray($list, 0, array(1024,1045,1023));

You could combine the two into one function, which will probably be faster but less useful for other tasks.

Tom Haigh
This will require two iterations - be careful with large arrays.
Stefan Gehrig
A: 

A very nice and flexible OOP-way is using the FilterIterator class (PHP >= 5.1.0):

class PrefixFilter extends FilterIterator 
{
    /**
     * @var string
     */
    protected $_prefix;

    /**
     * @param  Iterator $iterator
     * @param  string   $prefix
     */
    public function __construct(Iterator $iterator, $prefix)
    {
        parent::__construct($iterator);
        $this->_prefix = $prefix;
    }

    /**
     * @return boolean
     */
    public function accept()
    {
        if (!strlen($this->_prefix)) {
            return true;
        } else {
            $item = $this->getInnerIterator()->current();
            return (stripos($item[1], $this->_prefix) === 0);
        }
    }
}

class IdFilter extends FilterIterator 
{
    /**
     * @var array
     */
    protected $_ids;

    /**
     * @param  Iterator $iterator
     * @param  array    $ids
     */
    public function __construct(Iterator $iterator, array $ids)
    {
        parent::__construct($iterator);
        $this->_ids = $ids;
    }

    /**
     * @return boolean
     */
    public function accept()
    {
        $item = $this->getInnerIterator()->current();
        return (in_array($item[0], $this->_ids));
    }
}

This allows you to do the following:

$iterator = new IdFilter(
    new PrefixFilter(
        new ArrayIterator($list),
        ''
    ),
    array(1024, 1045, 1023)
);
foreach($iterator as $r) { 
    $size2 = $r[2]; 
    echo "<tr>
        <td id=\"id\"><span id=\"non_sorting_header\">" .$r[0]. "</span></td>
        <td id=\"name\"><span id=\"non_sorting_header\">" .$r[1]. "</span></td>
        <td id=\"speed\"><span id=\"sorting_header\">" .kMGTB2($size2). "</span></td>
        <td id=\"download\"><span id=\"sorting_header\">" .$r[3]. " Gb<br />per month</span></td>
        <td id=\"contract\"><span id=\"sorting_header\">1<br />month</span></td>
        <td id=\"info\"><span id=\"non_sorting_header\">".$r[5]."</span></td>
        <td id=\"buy\"><span id=\"non_sorting_header\">&pound;".$r[4]."<br />".$r[6]."</span></td>
      </tr>"; 
}

This way your filters are encapsulated into separate classes and they can be stacked arbitrarily. The overhead is small and you gain a lot in respect to design and reusability (and you can get rid of your dynamic function).

Stefan Gehrig