Jump to content

how to eliminate duplicates ?


sasori
Go to solution Solved by cpd,

Recommended Posts

hi, i have a huge object... to make it easy to understand my question..i printed out the ID and the itemID associated to it

147099 = 594088
147099 = 594086
147099 = 594085
147099 = 594082
147099 = 594083
147099 = 594089
161676 = 594091
196351 = 593971
196351 = 593904
196387 = 593894
196382 = 593892
196382 = 593891
196382 = 593889
196382 = 593888
196351 = 593887
196351 = 593865
196351 = 593864
196722 = 593798
196351 = 593795
196351 = 593794
196351 = 593793
196351 = 593792
196722 = 593790
196351 = 593789

how to skip the duplicates in that ^ ?

 

if am gonna use something like

$array = array_map( 'unserialize', array_unique( array_map( 'serialize', $array ),SORT_NUMERIC ) );

it will print only this

147099 = 594088

my actual goal is to print "1 unique id to each 1 unique itemid" like e.g 

147099 = 594088
161676 = 594091
196351 = 593971
196382 = 593892
196722 = 593798

so how ?

Link to comment
Share on other sites

the data came from this 

foreach($hugeobject as $k => $obj){
  echo $obj->userid . " = " . $obj->itemid."<br/>";
}

it got solved by this

$buffer = array();

foreach($hugeobject as $obj){
  if(isset($buffer[$obj->userid]))continue;

 $buffer[$obj->userid] = $obj;
}

foreach($buffer as $obj){
  echo $obj->userid . " = " . $obj->itemid . "<br/>";
}
Edited by sasori
Link to comment
Share on other sites

147099 = 594088
147099 = 594086
147099 = 594085
147099 = 594082
147099 = 594083
147099 = 594089

Each line is unique in itself. Just because you have 147099 many times it doesn't mean its not unique because they are relationships. That said, we don't know how the data is represented - as trq said - nor do we know what your system and its purpose is.

 

I could understand the purpose if you wanted to select only the ID part but you want both IDs so it doesn't really make sense at the moment.

Edited by cpd
Link to comment
Share on other sites

147099 = 594088
147099 = 594086
147099 = 594085
147099 = 594082
147099 = 594083
147099 = 594089

Each line is unique in itself. Just because you have 147099 many times it doesn't mean its not unique because they are relationships. That said, we don't know how the data is represented - as trq said - nor do we know what your system and its purpose is.

 

I could understand the purpose if you wanted to select only the ID part but you want both IDs so it doesn't really make sense at the moment.

 

 

i see ..... at the front-end , all i need is to display the image, item title ... any cool suggestions you might wanna throw in the given problem?

 

Link to comment
Share on other sites

So you want to display all the "item images" and "item titles" for each item? 

 

Are the items purchased by users or something? What does the key ID and value ID represent in your map above? E.g. your key ID represents a customer and the value ID is the ID of an item they purchased.

Link to comment
Share on other sites

So you want to display all the "item images" and "item titles" for each item? 

 

Are the items purchased by users or something? What does the key ID and value ID represent in your map above? E.g. your key ID represents a customer and the value ID is the ID of an item they purchased.

 

ok, these are the data that I needed to display

- Item Title

- item Price

- Item image

 

based from the map above,

 

the left side represents the UserID

while the right side represents the ItemID

 

the items were not purchased at all.. these items were posted by registered and non-registered users and are need to be displayed in a sliding manner.

there's also a possibility that the UserID is null if the item was posted by a guests .. ( guess I'll just remove that from the loop )

it goes like this.

 

- there is a square at the front-end

- inside that square ,there are four tabs

- in each tab, the items should be displayed where by , the sql statement is limited to 24 ,where in, each item is owned by a unique user

- under each tab. since the limit is 24 items per tab ,it should be displayed 6 at a time(paginated), in a sliding manner (powered by jquery slider )

(each tab has 24 items displayed based from the data fetched by sql )

Edited by sasori
Link to comment
Share on other sites

So list a few requirements as you've semi done already.

  1. The user will be able to view a list of all items
  2. The user will be able to view the title of an item
  3. The user will be able to view the price of an item
  4. The user will be able to view the image associated with an item

(verify number 1) Do we want to view who created the item? Are we taking this from the person who uploaded the items perspective? If so should they only see their items? If not I assume its from anybodies perspective and as such they can see all items? These questions will affect the logic in our system.

 

We aren't concerned with the way it looks at the moment, we just need the logic to retrieve what the requirements state we need the user to see.

Edited by cpd
Link to comment
Share on other sites

So list a few requirements as you've semi done already.

  1. The user will be able to view a list of all items
  2. The user will be able to view the title of an item
  3. The user will be able to view the price of an item
  4. The user will be able to view the image associated with an item

(verify number 1) Do we want to view who created the item? Are we taking this from the person who uploaded the items perspective? If so should they only see their items? If not I assume its from anybodies perspective and as such they can see all items? These questions will affect the logic in our system.

 

We aren't concerned with the way it looks at the moment, we just need the logic to retrieve what the requirements state we need the user to see.

 

1 ) Yes, but this is already accomplished because I got the UserID and can pass it to the href thing , and it will go to a different page already.

1-1 ) No. the display is viewed by public 

Link to comment
Share on other sites

Okay so you want to select all the items from the "item" table (whatever you called it) and join the user table. Then display the results. (This assumes you're using a database to store the items and users.

 

You can add the requirement to view no more than 24 items per page.

 

Does that make sense?

Edited by cpd
Link to comment
Share on other sites

Okay so you want to select all the items from the "item" table (whatever you called it) and join the user table. Then display the results. (This assumes you're using a database to store the items and users.

 

You can add the requirement to view no more than 24 items per page.

 

Does that make sense?

 

the join thing has been accomplished and was lumped in the $hugeObject, this huge object contains 24 items already based from the actual complex query

 

hence , I can display the items by :

 

$buffer = array();
 
foreach($hugeobject as $obj){
  if(isset($buffer[$obj->userid]))continue;


 $buffer[$obj->userid] = $obj;
}


foreach($buffer as $obj){
  echo $obj->userid . " = " . $obj->itemid . " = " . $item->price . " = " . $item->itemtitle ."<br/>";
}

sample data ( I don't have much unique dummy data)

 

Tab1
201087 = 627756 = 432 = testadaftermigration1
201147 = 627697 = 432 = forhim mediaplayer1-user4
201386 = 627696 = 432 = forhim software1-user3nonreg
201146 = 627695 = 432 = forhim mobile1-user3
200485 = 627170 = 199 = Google Nexus 7


Tab2
201387 = 627840 = 58 = Beautiful Dresses
200484 = 627733 = 39.9 = Dorothy Lace Waisted Flare Dress-Estelle
201146 = 627728 = 123 = spa
201147 = 627727 = 123 = haircare
201087 = 627723 = 2323 = cosmetics2
200903 = 627712 = 345.99 = Chanel Ring
201386 = 627690 = 123 = forher haircare1-user3nonreg


Tab3
201087 = 627758 = 123 = pp enabled1
201147 = 627700 = 123 = forkids bicycle1-user4
201386 = 627699 = 431 = forkids swimming1-user3 nonreg
201146 = 627698 = 323 = forkids book1-user2
201226 = 627636 = 23 = child case
200484 = 627082 = 1000 = IPhone 4S


Tab4
201387 = 627840 = 58 = Beautiful Dresses
200484 = 627733 = 39.9 = Dorothy Lace Waisted Flare Dress-Estelle
201146 = 627725 = 123 = bags1
200903 = 627712 = 345.99 = Chanel Ring
201087 = 627703 = 856 = forhousehold petgrooming1-user1
201148 = 627702 = 464 = forhousehold petadoption1-user5
201386 = 627681 = 321 = forher womanshoes1-user1nonreg
= 626769 = 2 = Elephant Ring

 

 

( but just like what you've said, you think something's gonna break.. i don't know what would that be )

Edited by sasori
Link to comment
Share on other sites

Okay we'll if you want to display all the items, and assuming you're not using an ORM, I'd have done something like

 

/**
 * Represents a single record from a database
 */
abstract class Record 
{
    /**
     * Contains data set using the __set() method.
     * 
     * @var array
     */
    protected $data = array();
    
    /**
     * Sets a value when set as if its an attribute of this object.
     * 
     * This is a default implementation and should be overriden if read-only access is requried.
     * 
     * @param mixed $name The name of the attribute
     * @param mixed $value The value the attribute references
     */
    public function __set($name, $value) 
    {
        $this->data[$name] = $value;
    }
    
    /**
     * Gets a value as if it were an attribute of this object
     * 
     * @param mixed $name The name of the attribute
     * @return mixed The value of the attribute
     * @throws Exception Thrown if the attribute couldn't be found
     */
    public function __get($name) 
    {
        $output = null;
        
        // Check if the variable is set, if not throw an exception
        if(isset($this->data[$name])) {
            $output = $this->data[$name];
        } else {
            throw new Exception("Attribute not found");
        }
        
        // Return the value
        return $output;
    }
}


/**
 * Represents a User within a database
 */
class User extends Record
{
    /**
     * Sets the internal attributes
     * 
     * @param int $userID
     * @param string $firstName
     * @param string $lastName
     */
    public function __construct($userID, $firstName, $lastName) 
    {
        $this->id = $userID;
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }
}


/**
 * Represents an Item within the database
 */
class Item extends Record
{
    /**
     * Contains the user who created this item
     * 
     * @var User
     */
    private $user = null;
    
    /**
     * Sets the user who created this item and the item attributes
     * 
     * @param User $user The user that created this item
     * @param int $itemId The item id
     * @param string $itemName The name of the item
     * @param string $itemImage The image associated with this item
     */
    public function __construct(User $user, $itemId, $itemName, $itemImage) 
    {
        $this->user = $user;
        $this->id = $itemId;
        $this->name = $itemName;
        $this->image = $itemImage;
    }
    
    /**
     * Gets the user who crated this item
     * 
     * @return User
     */
    public function getUser()
    {
        return $this->user;
    }
}

$sql = "SELET Items JOIN Users...";
$result = ...;

// Create an iterator for the items
$iterator = new ArrayIterator();

// Loop through the results however you want depending on how you got the result
while($row = mysqli_fetch_assoc($result)) {    
   $iterator->append(
      new Item(
         new User(
            $row['userId'],
            $row['firstName'],
            $row['lastName']
         ),
         $row['itemID'],
         $row['itemName'],
         $row['itemImage']
      );
}

<?php

// Now within your HTML document you can do
while($iterator->valid()) :    
   $item = $iterator->current(); ?> 
Print out your HTML using the item E.g. <?=$item->id;?> <?=$item->getUser()->fisrtName;?>

<?php
    $iterator->next();
endwhile;
?>

This sort method would get all the users and create objects for them adding them to an iterator you can then cycle through to output the items.

 

EDIT: Sorry for all the edits. Noticed I tried overriding a property and changing its visibility which isn't allowed.

Edited by cpd
Link to comment
Share on other sites

And an implementation with read-only access since you're not using an ORM and therefore the values shouldn't really be changed in this instance.

 

/**
 * Represents a single record from a database
 */
abstract class Record 
{
    /**
     * Contains data set using the __set() method.
     * 
     * @var array
     */
    private $data = array();
    
    /**
     * Sets a value when set as if its an attribute of this object.
     * 
     * This is a default implementation and should be overriden if read-only access is requried.
     * 
     * @param mixed $name The name of the attribute
     * @param mixed $value The value the attribute references
     */
    public function __set($name, $value) 
    {
        $this->data[$name] = $value;
    }
    
    /**
     * Gets a value as if it were an attribute of this object
     * 
     * @param mixed $name The name of the attribute
     * @return mixed The value of the attribute
     * @throws Exception Thrown if the attribute couldn't be found
     */
    public function __get($name) 
    {
        $output = null;
        
        // Check if the variable is set, if not throw an exception
        if(isset($this->data[$name])) {
            $output = $this->data[$name];
        } else {
            throw new Exception("Attribute not found");
        }
        
        // Return the value
        return $output;
    }
}


abstract class ReadOnlyRecord extends Record 
{    
    /**
     * Creates read-only access to this object
     */
    public function __set($name, $value) 
    {
    }
    
    /**
     * Allows child classes to set data internally still. This method should be used to 
     * set any data within the scope of the object.
     * 
     * @param string $name
     * @param string $value
     */
    protected final function set($name, $value) 
    {
        parent::__set($name, $value);
    }
}


/**
 * Represents a User within a database
 */
class User extends ReadOnlyRecord
{
    /**
     * Sets the internal attributes
     * 
     * @param int $userID
     * @param string $firstName
     * @param string $lastName
     */
    public function __construct($userID, $firstName, $lastName) 
    {
        $this->set('id', $userID);
        $this->set('firstName', $firstName);
        $this->set('lastName', $lastName);
    }
}


/**
 * Represents an Item within the database
 */
class Item extends ReadOnlyRecord
{
    /**
     * Contains the user who created this item
     * 
     * @var User
     */
    private $user = null;
    
    /**
     * Sets the user who created this item and the item attributes
     * 
     * @param User $user The user that created this item
     * @param int $itemId The item id
     * @param string $itemName The name of the item
     * @param string $itemImage The image associated with this item
     */
    public function __construct(User $user, $itemId, $itemName, $itemImage) 
    {
        $this->user = $user;
        $this->set('id', $itemId);
        $this->set('name', $itemName);
        $this->set('image', $itemImage);
    }
    
    /**
     * Gets the user who crated this item
     * 
     * @return User
     */
    public function getUser()
    {
        return $this->user;
    }
}

Both implementations get the items and display them. The logic for how many you display is elsewhere; you can use your query to manage this.

 

My point here is instead of wrapping everything up into one big object, break it down. 

Edited by cpd
Link to comment
Share on other sites

awesome...can you help me paginate the result data? , based from the sample data result that I pasted?

assuming there are 24 items per tabs, and each page per tab should display 6 per page

Edited by sasori
Link to comment
Share on other sites

  • Solution

I've created a simple implementation of paginating content. It's okay but the __toString() method could do with being broken up and you could add additional customisations such as what tags the pagination will use.

 

/**
 * A configuration object for the paginate class
 */
class PaginateConfig
{
    /**
     * The URL the buttons should link to. This should contain the PAGE_NUM_REGEX
     * 
     * @var string
     */
    private $url = null;
    
    /**
     * The class to apply to the wrapper of the paginate
     * 
     * @var string
     */
    private $wrapperClass = null;
    
    /**
     * The class to apply to the numbers of the paginate
     * 
     * @var string
     */
    private $numberClass = null;
    
    /**
     * The class to apply to the buttons of the paginate
     * 
     * @var string
     */
    private $buttonClass = null;
    
    /**
     * Sets internal attributes. Will throw an Exception if it doesn't find a the Paginate::PAGE_NUM_REGEX 
     * in the URL. 
     *
     * @param string $url The URL to use for pagination
     * @param string $wrapperClass The wrapper class
     * @param string $numberClass The number class
     * @param string $buttonClass The button class
     */
    public function __construct($url, $wrapperClass = null, $numberClass = null, $buttonClass = null) 
    {
        $this->setUrl($url);
        $this->wrapperClass = $wrapperClass;
        $this->numberClass = $numberClass;
        $this->buttonClass = $buttonClass;
    }
    
    private function setUrl($url) 
    {
        // Create an array to hold the matches and find matche
        $matches = array();
        preg_match("/" . preg_quote(Paginate::PAGE_NUM_REGEX) . "/", $url, $matches);
        
        // If the matches array contains less than 2 elements throw an error
        if(count($matches) != 1) {
            throw new Exception("Could not find page number regex or there were too many occurences");
        }
        
        $this->url = $url;
    }
    
    /**
     * Gets the URL
     * 
     * @return string
     */
    public function getUrl()
    {
        return $this->url;
    }


    /**
     * Gets the wrapper class
     * 
     * @return string
     */
    public function getWrapperClass()
    {
        return $this->wrapperClass;
    }


    /**
     * Gets the number lcass
     * 
     * @return strnig
     */
    public function getNumberClass()
    {
        return $this->numberClass;
    }


    /**
     * Gets the button class
     * 
     * @return string
     */
    public function getButtonClass()
    {
        return $this->buttonClass;
    }
}


/**
 * Geneates page numbers as links to flick through content
 */
class Paginate
{
    /**
     * The regex paginate will look for to replace with a page number
     */
    const PAGE_NUM_REGEX = "{:page}";
    
    /**
     * The configuration of this Paginate
     * 
     * @var PaginateConfig
     */
    private $config = null;
    
    /**
     * The current page we're on
     * 
     * @var int
     */
    private $currentPage = null;
    
    /**
     * How many items per page
     * 
     * @var int
     */
    private $itemsPerPage = null;
    
    /**
     * The total items per page
     * 
     * @var int 
     */
    private $totalItems = null;
    
    /**
     * The total pages available
     * 
     * @var int
     */
    private $totalPages = null;
    
    /**
     * Sets the internal attributes.
     * 
     * @param int $currentPage The page we're currently on
     * @param int $itemsPerPage The total items per page
     * @param int $totalItems The total items
     * @param PaginateConfig $config The configuration to use
     */
    public function __construct(PaginateConfig $config, $currentPage, $itemsPerPage, $totalItems)
    {
        $this->config = $config;
        $this->itemsPerPage = $itemsPerPage;
        $this->totalItems = $totalItems;
        $this->totalPages = ceil($totalItems / $itemsPerPage);
        
        $this->setCurrentPage($currentPage);
    }
    
    /**
     * Sets the paginate configuration
     * 
     * @param PaginateConfig $config The configuraton to use
     */
    public function setConfig(PaginateConfig $config) 
    {
        $this->config = $config;
    }
    
    /**
     * Sets the current page. If the current page is less than 1 or greater than the total pages
     * the current page will be set to 1.
     * 
     * @param int $page The current page
     */
    private function setCurrentPage($page) 
    {
        if($page > $this->totalPages || $page < 1) {
            $this->currentPage = 1;
        } else {
            $this->currentPage = $page;
        }
    }
    
    /**
     * Formats the URL provided by the configuration with the page number
     * 
     * @param int $num The number to format the URL with
     * @return string The formatted URL
     */
    private function formatUrl($num) 
    {
        return preg_replace("/" . preg_quote(self::PAGE_NUM_REGEX) . "/", $num, $this->config->getUrl());
    }
    
    /**
     * Generates the pagination adding any classes set in the configuration
     * 
     * @return string
     */
    public function __toString() 
    {
        $class = array();
        $class['wrapper'] = $this->config->getWrapperClass();
        $class['number'] = $this->config->getNumberClass();
        $class['button'] = $this->config->getButtonClass();
        
        // Add the wrapper and previous page tags
        $output = "<div " . ($class['wrapper'] != null ? "class=\"" . $class['wrapper'] ."\"" : "") . ">";
        $output.= "<a " . ($class['button'] != null ? "class=\"" . $class['button'] . "\"" : "")
            . " href=\"" . ($this->currentPage > 1 ? $this->currentPage-1 : 1) 
            . "\">«</a>";
        
        // Add the page
        for($i = 1; $i <= $this->totalPages; $i++) {
            $output.= "<a " . ($class['button'] != null ? "class=\"" . $class['button'] . "\"" : "") . " href=\"" . $this->formatUrl($i) . "\">" . $i . "</a>";
        }
        
        // Add the next page and wrapper close tag
        $output.= "<a " . ($class['button'] != null ? "class=\"" . $class['button'] . "\"" : "") 
            . " href=\"" . ($this->currentPage < $this->totalPages ? $this->currentPage+1 : $this->totalPages) 
            . "\">»</a>";
        $output.= "</div>";
        
        return $output;
    }
}




$paginate = new Paginate(
    new PaginateConfig("http://www.domain.com/blog/" . Paginate::PAGE_NUM_REGEX), 
    6, 5, 16
);


echo $paginate;
Edited by cpd
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.