【问题标题】:PHP Array ParsingPHP 数组解析
【发布时间】:2009-08-03 22:23:16
【问题描述】:

大家好,我有一个庞大的数组作为搜索结果返回,我想要执行以下操作:

遍历数组并为每个具有相同“spubid”的记录添加以下键/值:“sfirst, smi, slast”到本例中的父数组成员 $a[0]。所以结果将保留$a[0],但添加来自数组中其他成员的sfirst、smi 和slast 的值(因为它们都具有相同的“spubid”)。我认为将键值 (1, 2, 3) 添加到关联键 (sfirst1=> "J.", smi1=>"F.", slast1=>"Kennedy") 就可以了。然后我想用那个“spubid”删除(unset())数组中的其余成员。这是我返回的数组的简化示例,在此示例中,所有记录都具有相同的“spubid”:

Array ( 
  [0] => 
    Array ( 
      [spubid] => A00502 
      [sfirst] => J. 
      [smi] => A. 
      [slast] => Doe
  [1] => 
    Array ( 
      [spubid] => A00502 
      [sfirst] => J. 
      [smi] => F. 
      [slast] => Kennedy 
  [2] => 
    Array ( 
      [spubid] => A00502 
      [sfirst] => B. 
      [smi] => F. 
      [slast] => James 
  [3] => 
    Array ( 
      [spubid] => A00502
      [sfirst] => S. 
      [smi] => M. 
      [slast] => Williamson 
      )
    )

所以本质上我想保留 $a[0] 但向它添加新的键=>值(sfirst$key,smi$key,slast$key)并附加来自“sfirst,smi,slast”的值所有具有相同“spubid”的成员然后取消设置 $a[1]-[3]。

只是为了澄清我的理想最终结果是:

Array ( 
  [0] => 
    Array ( 
      [spubid] => A00502 
      [sfirst] => J. 
      [smi] => A. 
      [slast] => Doe
      [sfirst1] => J.
      [smi1] => F. 
      [slast1] => Kennedy
      [sfirst2] => B. 
      [smi2] => F. 
      [slast2] => James 
      [sfirst3] => S. 
      [smi3] => M. 
      [slast3] => Williamson
    )
  )

在大多数情况下,我会从一个更大的数组开始,其中包括大量“spubid”,但 99% 的出版物都有不止一个作者,所以这个例程对于清理结果和制作非常有用显示的解析过程更容易。

***更新

我认为通过过度简化我的示例可能会使事情变得不清楚。我喜欢 Chacha102 和 zombat 的响应,但我的“父数组”包含的不仅仅是一个 pubid,它恰好是主键。我需要保留该记录中的许多其他数据,其中一小部分如下:

[spubid] => A00680 
[bactive] => t 
[bbatch_import] => t 
[bincomplete] => t 
[scitation_vis] => I,X 
[dentered] => 2009-08-03 12:34:14.82103 
[sentered_by] => pubs_batchadd.php 
[drev] => 2009-08-03 12:34:14.82103 
[srev_by] => pubs_batchadd.php 
[bpeer_reviewed] => t 
[sarticle] => A case study of bora-driven flow and density changes on the Adriatic shelf (January 1987)
.
.
.
.
.

每个搜索查询都会返回大约 40 列。与其像这些示例对 pubid 那样对它们进行硬编码,我如何在包含它们的同时仍然按照你们的建议进行更改。创建一个多维数组(正如你们俩所建议的那样),作者是多维的一部分,非常好,谢谢你们的建议。

**** 更新:

这是我确定的解决方案,非常简单并且可以很好地完成工作。我最终确实创建了一个多维数组,所以作者在那里被打破了。

过度简化的解决方案:

$apubs_final = array();
$spubid = NULL;
$ipub = 0;

foreach($apubs as $arec)
{
  if($spubid != $arec['spubid'])
  {
    $ipub++;
    $apubs_final[$ipub] = $arec;
    // insert UNSET statements here for author data
    $iauthor = 0;
    $spubid = $arec['spubid'];
  }
  $iauthor++;
  $apubs_final[$ipub]['authors'][$iauthor]['sauthor_first'] = $arec['sfirst'];
} 

感谢所有回复的人,非常感谢您的帮助!

【问题讨论】:

  • 获得一组作者数组是否更容易,每个数组都包含 sfirst、smi 和 slast?
  • 那里,我在回答中为你做了两种方式,以防你愿意切换到不同的格式。
  • 那里,已经进行了更改。
  • 你如何处理你最终得到的数组?为什么它需要采用这种格式?
  • 匈牙利符号让我眼睛流血。

标签: php arrays parsing


【解决方案1】:
// First, probably the more parsable way.
foreach($array as $key => $values)
{
    $end[$spuid] = $values;
    $spuid = $values['spuid']
    $end[$spuid]['authors'][] = array('sfirst' => $values['sfirst'],
                          'smi' => $values['smi'],
                           'slast' => $values['slast']);

}

会得到这样的数组

Array(
    [A00502] =>
         Array(
           [supid] => A00502
               .... other values .....
           [authors] =>
                 Array(
                [0]=>
                      Array(
                    ['sfirst'] => '',
                    ['smi'] => '',
                    ['slast'] => '')
                )
        )
)

如果您打算在页面上显示这种方式,我发现这种方式更易于解析,因为它使用数组,因此您可以访问作者,这就是我看到很多人为这样的属性所做的方式.

如果您确实想要理想的格式,请稍后使用此格式

$count = 0;
foreach ($end as $supid => $values)
{
    $other_end[$count] = $values;
    $other_end[$count]['spuid'] = $spuid;
    foreach($values['authors'] as $key => $author)
    {
        if($key == 0)
        {
            $suffix = '';
        }
        else
        {
            $suffix = $key;
        }
        $other_end[$count]['sfirst'.$suffix] = $author['sfirst'];
        $other_end[$count]['smi'.$suffix] = $author['smi'];
        $other_end[$count]['slast'.$suffix] = $author['slast'];
    }

}

【讨论】:

  • 很好的解决方案,我编辑了原始帖子,因为我稍微简化了一些事情,从而使我的整体问题不清楚。我道歉!
  • 已更新,非常相似,您可能还有一些额外的键,但它们都会在那里。
  • 基本上,您将拥有数组中最后一个人的额外的第一个中间名和姓氏,但这不会有太大影响。
  • 你更新的解决方案让我到达了我需要的地方,我用我确定的解决方案编辑了我的原始帖子。再次非常感谢您所做的一切。
  • 你知道所有回答这个问题的人都在等着看你给谁接受的答案。 :P
【解决方案2】:

为什么不创建一个以 spubid 为键的数组:

// assuming $array is your array:

$storage = array();
foreach($array as $entry) {
  $bid = $entry['spubid'];
  if (!isset($storage[$bid])) {
    // duplicate entry - taking the author out of it.
    $stortmp = $entry;
    unset($stortmp['sfirst'], $stortmp['smi'], $stortmp['slast']);
    // add an authors array
    $stortmp['authors'] = array();
    $storage[$bid] = $stortmp;
  }
  $author = array(
    'sfirst' => $entry['sfirst'], 
    'smi' => $entry['smi'], 
    'slast' => $entry['slast']);
  $storage[$bid]['authors'][] = $author;
}

现在您的 $storage 数组应该如下所示:

Array(
  "A00502" => Array(
    "spubid" => "A00502",
    "authors" => Array(
      [0] => 
        Array ( 
          [sfirst] => J. 
          [smi] => A. 
          [slast] => Doe
       [1] => 
         Array ( 
          [sfirst] => J. 
          [smi] => F. 
          [slast] => Kennedy

您可以轻松地对作者进行 foreach 以打印它们:

foreach ($storage as $pub) {
  echo 'Pub ID: '.$pub['spubid']."<br/>";
  foreach ($pub['authors'] as $author) {
    echo 'Author: '.$author['sfirst'].' '.$author['smi'].' '.$author['slast']."<br/>";
  }
}

另外,您还可以访问$storage['A00502']

已更新以征求意见

看来您的数组可能来自某种 SQL 查询,该查询涉及从出版物表到作者表的 JOIN。这会使您的结果数据集重复很多它并不真正需要的信息。没有理由多次从数据库传输/检索所有发布数据。尝试重写它以获取它要显示的所有书籍的查询,然后有一个“作者”查询,它执行以下操作:

SELECT * FROM authors WHERE spubid IN ('A00502', 'A00503', 'A00504');

然后将其转换为此数组以用于您的显示目的。您的数据库流量水平将感谢您。

【讨论】:

  • 这没有按预期工作,我仍在保留所有重复的数据。我在原始帖子中过度简化了我的示例,我确信这具有误导性。我已经扩展了这个例子。
  • 我已经编辑了示例以向您展示如何保留所有数据,但让我认为您的问题更多地与您的数据集有关。答案末尾有一段关于此的内容。
  • 这实际上是我最初的方法,使用一个查询来获取所有 pub 信息,然后使用一个单独的查询来获取作者。 个人更喜欢这种方法,因为您只是在数据库中查询您需要的数据。然而,权力告诉我,我不能使用这种方法,需要通过一个查询来完成所有操作。因此 NESTED 加入...
【解决方案3】:

此代码应该完全按照您指定的方式工作。我采取了使用几个临时数组的方法来在主数组键和spubid 子键之间进行关联。

/* assume $array is the main array */
$array = array(
    array('spubid' => 'A00502','sfirst'=>'J.','smi'=>'A.','slast'=>'Doe'),
    array('spubid' => 'A00502','sfirst'=>'J.','smi'=>'F.','slast'=>'Kennedy'),
    array('spubid' => 'A00502','sfirst'=>'B.','smi'=>'F.','slast'=>'James'),
    array('spubid' => 'BXXXXX','sfirst'=>'B.','smi'=>'F.','slast'=>'James'),
    array('spubid' => 'A00502','sfirst'=>'S.','smi'=>'M.','slast'=>'Williamson')
);

//track spubid positions in the main array
$keyPositions = array();
//keys to delete after array iteration
$keyDel = array();
//track how many spubkey increments you've made to the fields
$spubKeys = array();
//fields to copy between spubids
$copyFields = array('sfirst','smi','slast');

foreach($array as $key => $subarr)
{
    if (isset($subarr['spubid'])) {
        if (isset($keyPositions[$subarr['spubid']])) {
            //spubid already exists at a main array key, do the copy
            $spubKey = ++$spubKeys[$subarr['spubid']];
            foreach($copyFields as $f) {
                $array[$keyPositions[$subarr['spubid']]][$f.$spubKey] = $subarr[$f];
            }
            $keyDel[] = $key;
        }
        else {
            //First time encountering this spubid, mark the position
            $keyPositions[$subarr['spubid']] = $key;
            $spubKeys[$subarr['spubid']] = 0;
        }
    }
}
if (count($keyDel)) {
    foreach($keyDel as $idx) unset($array[$idx]);
}

var_dump($array);

【讨论】:

  • 由于对相关数据进行了一些过度简化,因此编辑了原始帖子。你能再看看吗?再次感谢您的出色解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-26
相关资源
最近更新 更多