Jump to content

How to get unique field values from a nested foreach


NooseLadder
 Share

Recommended Posts

Hi,

$categories = $page->children; 
   foreach ($categories as $category) {
     $categoryNames = $category->categories;
        foreach ($categoryNames as $categoryName) {
        echo $categoryName->title."<br />";
        }
    }

This code gives output:

apple
orange
pear
banana
grape
kiwi
blackberry
passion
fig
apple
orange
pear
banana

I would like to only output unique values. I want to create only unique category links on the page regardless of how many child pages have duplicate categories. Can anyone point me in the right direction?

Link to comment
Share on other sites

$categories are already unique in the page tree. It's the $categoryName that I want unique. I have tried

$categories = $page->children; 
foreach ($categories as $category) {
$categoryNames = $category->categories;

$categoryNames = $categoryNames->unique();

foreach ($categoryNames as $categoryName) {
echo $categoryName->title."<br />";
}
}

And this

$categories = $page->children; 
foreach ($categories as $category) {
$categoryNames = $category->categories;
foreach ($categoryNames as $categoryName) {

$categoryName = $categoryName->unique();

echo $categoryName->title."<br />";
}
}

But they don't work.

This is the page tree:

The field categories is a multi page select.

Category List (where I want to list unique categories)

       Cat1 (has field categories containing 1 categories = fig)

       Cat2 (has field categories containing 4 categories = apple, orange, pear, banana)

       Cat3 (has field categories containing 8 categories = apple, orange, pear, banana, grape, kiwi, blackberry, passion)

Link to comment
Share on other sites

How about this (untested)...

$categories = $page->children;

/**
 * This will hold unique values from the possible repeats in your page tree...
 */
$uniques = array();

/**
 * Iterate as you did before but only keep one copy of each category you visit.
 */
foreach ($categories as $category) {
    $categoryNames = $category->categories;
    foreach ($categoryNames as $categoryName) {
        $uniques[$categoryName->id] = $categoryName->title;
    }
}

/**
 * Now do what you want with the uniques. They are indexed by page id.
 */
foreach ($uniques as $id => $title) {
    echo $title, "<br />\n";
}

...?

  • Like 4
Link to comment
Share on other sites

  • 5 months later...

Can someone explain to me how to use $a->unique();? 

<?php foreach($pages->find("template=item, editorial!='', sort=editorial") as $item) {
 echo $item->editorial;
} ?>

Retrieves a list of publishers ("editorial" field) from a template called "item", but with duplicates:

  1. Abada
  2. Abada
  3. Abada
  4. Academy of Mathematics and Systems Science
  5. Chinese Academy of Sciences
  6. Actar
  7. Actar
  8. etc...

How can I remove the duplicates from this simple loop?

Link to comment
Share on other sites

As I understand it, you have different items the same editorial (as a text field), and you want to get an array with unique editorils, right? If so, here is the code to get this:

$editorials = array();
$lastEditorial = null;
foreach ($pages->find("template=item, editorial!='', sort=editorial") as $item) {
  if ($item->editorial !== $lastEditorial) $editorials[] = $item->editorial;
  $lastEditorial = $item->editorial;
}

$a->unique() filters elements using the PHP array_unique function, which compares elements according to their string representation. Since the result of $pages->find() returns a PageArray containing Page objects, and since the string representation of a Page object is its id, $pages->find(...)->unique will return unique pages, without considering the editorial field (two different pages with the same editorial will be different, since they will have different ids). That's why $a->unique isn't usable in your case.

  • Like 4
Link to comment
Share on other sites

Thanks ESRCH for your explanation. I understand now why $a->unique() isn't working. However, I don't understand your code, especially the $lastEditorial variable. And I don't know how to echo it either... 

But you guessed what I wanted to achieve: I have a list of books where various editors typed in publishers manually in a text field, instead of pulling them from a predefined list. Hence my issue with the duplicates: I want a "clean" array with unique publishers.

Link to comment
Share on other sites

The code from my previous post generates a simple array of editor names, over which you can loop, for example like this:

// $editorials is the array from the code above
foreach ($editorials as $editorial) {
  echo $editorial;
}

The $lastEditorial variable is simply used to avoid duplicates: In the code of the previous post, each iteration first compares the editor ($item->editorial) with the value it had for the previous iteration ($lastEditorial), and if it is not the same, it include it in the new array ($editorials[] = $item->editorial). Then at the end of the loop, the $lastEditorial is updated to have the new value. So using the data that you gave, the iterations go like this:

  1. "Abada" !== "", so add "Abada" to the $editorials array. Set $lastEditorial to "Abada"
  2. "Abada" === "Abada", so don't add the new "Abada" to the loop. Set $lastEditorial to "Abada"
  3. "Abada" === "Abada", so don't add the new "Abada" to the loop. Set $lastEditorial to "Abada"
  4. "Academy of Mathematics" !== "Abada", so add "Academy of Mathematics to the $editorials array. Set $lastEditorial to "Academy of Mathematics"
  5. "Chinese Academy" !== "Academy of Mathematics", so add "Chinese Academy..." to the $editorials array. Set $lastEditorial to "Chinese Academy..."
  6. etc.

The result of this all is to have an array of unique editors.

But if you really just want to echo the editors in place, you can shorten your code to one loop (I also reduced the number of variable assignments):

$editorials = array();
$lastEditorial = "";
foreach($pages->find("template=item, editorial!='', sort=editorial" as $item) {
  if ($item->editorial !== $lastEditorial) {
    echo $item->editorial;
    $lastEditorial = $item->editorial;
  }
}
  • Like 2
Link to comment
Share on other sites

ESRCH, you're such a great teacher. I've understood it perfectly. Very smart solution. I love this forum, I always learn something new. Now I have to up my PHP game to be able to return the favor and contribute more.  

  • Like 3
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...