Birleşmeli dizideki iki öğe Anahtarı

11 Cevap php

Örnek:

$arr = array(
  'apple'      => 'sweet',
  'grapefruit' => 'bitter',
  'pear'       => 'tasty',
  'banana'     => 'yellow'
);

Ben greyfurt ve armut pozisyonları geçmek istiyorum, bu yüzden dizi olacak

$arr = array(
  'apple'      => 'sweet',
  'pear'       => 'tasty',
  'grapefruit' => 'bitter',
  'banana'     => 'yellow'
)

Ben geçmek istiyorum elemanlarının anahtarlarını ve değerlerini bilmek, bunu yapmak için kolay bir yolu var mı? Yoksa yeni bir dizi oluşturma, bir döngü + gerektirir?

Teşekkürler

11 Cevap

Kolay yolu, sadece bir döngü ya da yeni bir dizi tanımı yoktur.

Ve sana bir sorum var: Bu gerçekten yararlıdır? Onlara anahtarlama ne kolaylık var?

Sadece küçük bir kısa ve arcaneerudite çözümüne göre daha az karmaşık:

<?php
if(!function_exists('array_swap_assoc')) {
    function array_swap_assoc($key1, $key2, $array) {
        $newArray = array ();
        foreach ($array as $key => $value) {
            if ($key == $key1) {
                $newArray[$key2] = $array[$key2];
            } elseif ($key == $key2) {
                $newArray[$key1] = $array[$key1];
            } else {
                $newArray[$key] = $value;
            }
        }
        return $newArray;
    }
}

$array = $arrOrig = array(
    'fruit' => 'pear',
    'veg' => 'cucumber',
    'tuber' => 'potato',
    'meat' => 'ham'
);

$newArray = array_swap_assoc('veg', 'tuber', $array);

var_dump($array, $newArray);
?>

Test edilmiş ve gayet iyi çalışıyor

Bunu yapmanın kolay bir yolu yoktur. Bu yapmak isteyen ne olursa olsun yapmak için daha iyi bir yolu varken bunu yapmak için denemek için size yol açmıştır sizin açınızdan hafif bir tasarım-mantık hatası gibi geliyor. Bunu yapmak istiyorum neden bize söyleyebilir misin?

Sen I know the keys and values of the elements I want to switch, kolayca her zaman olduğu gibi istediğiniz doğru öğeleri erişebilirsiniz beri bana ne gerçekten istediğiniz bir sıralama işlevi olduğunu düşünüyorum yapar söylüyorlar.

$value = $array[$key];

Bu durumda o zaman istediğiniz kadar dizisini almak için sort(), ksort() veya diğer birçok sıralama işlevlerinden birini kullanabilirsiniz. Hatta usort() Sort an array by values using a user-defined comparison function için kullanabilirsiniz.

Hiç değerleri veya anahtarları takas gerekiyorsa array_replace() kullanabileceğiniz dışında.

dizi db gelirse her zaman elemanları dizide ne sipariş emin olabilirsiniz, bir sıra_düzeni alanını ekleyin.

Bu, ya da belirli bir use-case bağlı bir seçenek olmayabilir, ancak veri ile doldurmadan önce uygun anahtarlar ile null değerleri ile dizinizi başlatabilirsiniz eğer, herhangi bir sırayla ve orijinal anahtar sırayla olacak değerleri ayarlayabilirsiniz korunabilir. Peki yerine elemanları takas, tamamen onları takas için ihtiyaç önleyebilirsiniz:

$arr = array('apple' => null,
             'pear' => null,
             'grapefruit' => null,
             'banana' => null);

...

$arr['apple'] = 'sweet';
$arr['grapefruit'] = 'bitter'; // set grapefruit before setting pear
$arr['pear'] = 'tasty';
$arr['banana'] = 'yellow';
print_r($arr);

>>> Array
(
    [apple] => sweet
    [pear] => tasty
    [grapefruit] => bitter
    [banana] => yellow
)

Dışı endeksli çünkü tamamen bu sözü eğer emin değil, bu zor nedenidir.

En atalım:

$arrOrig = array(
  'fruit'=>'pear',
  'veg'=>'cucumber',
  'tuber'=>'potato'
);

Tuşları alın:

$arrKeys = array_keys($arrOrig);
print_r($arrKeys);
Array(
 [0]=>fruit
 [1]=>veg
 [2]=>tuber
)

Değerleri elde edersiniz:

$arrVals = array_values($arrOrig);
print_r($arrVals);
Array(
  [0]=>pear
  [1]=>cucumber
  [2]=>potato
)

Şimdi sayısal 2 Hangi diziler var. Takas etmek istediğiniz olanların endeksleri Swap, daha sonra değiştirilmiş sayısal dizinin sırayla geri diğer dizi okudum. Kullanıcının biz 'meyve' ve 'sebze' takas etmek istediğinizi varsayalım:

$arrKeysFlipped = array_flip($arrKeys);
print_r($arrKeysFlipped);
Array (
 [fruit]=>0
 [veg]=>1
 [tuber]=>2
)
$indexFruit = $arrKeysFlipped['fruit'];
$indexVeg = $arrKeysFlipped['veg'];
$arrKeysFlipped['veg'] = $indexFruit;
$arrKeysFlipped['fruit'] = $indexVeg;
print_r($arrKeysFlipped);
Array (
 [fruit]=>1
 [veg]=>0
 [tuber]=>2
)

Şimdi, diziyi geri takas edebilirsiniz:

$arrKeys = array_flip($arrKeysFlipped);
print_r($arrKeys);
Array (
 [0]=>veg
 [1]=>fruit
 [2]=>tuber
)

Şimdi, yeniden düzenlenmiş tuşlarının 'sipariş' Oringal dizi geçerek bir dizi oluşturabilirsiniz.

$arrNew = array ();
foreach($arrKeys as $index=>$key) {
  $arrNew[$key] = $arrOrig[$key];
}
print_r($arrNew);
Array (
 [veg]=>cucumber
 [fruit]=>pear
 [tuber]=>potato
)

Ben bu test değil - ama bu ne beklersiniz, değil. Bu, en azından her türlü yardımı sağlıyor mu? İyi şanslar :)

Eğer bir fonksiyon içine koyabilirsiniz $arrNew = array_swap_assoc($key1,$key2,$arrOld);

<?php
if(!function_exists('array_swap_assoc')) {
    function array_swap_assoc($key1='',$key2='',$arrOld=array()) {
       $arrNew = array ();
       if(is_array($arrOld) && count($arrOld) > 0) {
           $arrKeys = array_keys($arrOld);
           $arrFlip = array_flip($arrKeys);
           $indexA = $arrFlip[$key1];
           $indexB = $arrFlip[$key2];
           $arrFlip[$key1]=$indexB;
           $arrFlip[$key2]=$indexA;
           $arrKeys = array_flip($arrFlip);
           foreach($arrKeys as $index=>$key) {
             $arrNew[$key] = $arrOld[$key];
           }
       } else {
           $arrNew = $arrOld;
       }
       return $arrNew;
    }
}
?>

UYARI: Sadece kullanmadan önce bu test ve hata ayıklama - Lütfen hiçbir test tüm yapılmıştır.

Burada swap fonksiyonu benim sürümü bulunuyor:

function array_swap_assoc(&$array,$k1,$k2) {
  if($k1 === $k2) return;  // Nothing to do

  $keys = array_keys($array);  
  $p1 = array_search($k1, $keys);
  if($p1 === FALSE) return;  // Sanity check...keys must exist

  $p2 = array_search($k2, $keys);
  if($p2 === FALSE) return;

  $keys[$p1] = $k2;  // Swap the keys
  $keys[$p2] = $k1;

  $values = array_values($array); 

  // Swap the values
  list($values[$p1],$values[$p2]) = array($values[$p2],$values[$p1]);

  $array = array_combine($keys, $values);
}

Klasik ilişkisel dizi herhangi bir şekilde elemanların sırasını tanımlamak veya garanti vermez. Bunun için düz dizi / vektör var. Ilişkilendirilebilir dizi kullanırsanız size rasgele erişim ama sıralı gerekmez varsayılır. Benim için bunun için yapılmış değildir görev için doç dizi kullanıyor.

Eğer onlar bunun yerine dizi nasıl düzenlendiğine bağlı olarak erişilen nasıl mantık kolu kullanarak neden, verileri tutmak için ilişkilendirilebilir bir dizi kullanarak eğer evet ben, Lex katılıyorum.

Eğer gerçekten emin onlar meyve nesneleri oluşturmak çalışıyorum, doğru bir düzeni vardı ve daha sonra normal bir dizide koymak yapmak istedim.

İşte iki çözüm vardır. İlk uzun, ama geçici bir dizi oluşturmak değil, bu nedenle bellek kaydeder. İkinci muhtemelen daha hızlı çalışır, ancak daha fazla bellek kullanır:

function swap1(array &$a, $key1, $key2)
{
  if (!array_key_exists($key1, $a) || !array_key_exists($key2, $a) || $key1 == $key2) return false;

  $after = array();
  while (list($key, $val) = each($a))
  {
    if ($key1 == $key)
    {
      break;
    }
    else if ($key2 == $key)
    {
      $tmp = $key1;
      $key1 = $key2;
      $key2 = $tmp;
      break;
    }
  }

  $val1 = $a[$key1];
  $val2 = $a[$key2];

  while (list($key, $val) = each($a))
  {
    if ($key == $key2)
      $after[$key1] = $val1;
    else
      $after[$key] = $val;
    unset($a[$key]);
  }

  unset($a[$key1]);
  $a[$key2] = $val2;

  while (list($key, $val) = each($after))
  {
    $a[$key] = $val;
    unset($after[$key]);
  }

  return true;
}

function swap2(array &$a, $key1, $key2)
{    
  if (!array_key_exists($key1, $a) || !array_key_exists($key2, $a) || $key1 == $key2) return false;

  $swapped = array();

  foreach ($a as $key => $val)
  {
    if ($key == $key1)
      $swapped[$key2] = $a[$key2];
    else if ($key == $key2)
      $swapped[$key1] = $a[$key1];
    else
      $swapped[$key] = $val;
  }

  $a = $swapped;

  return true;
}

Php diziler haritalar sıralanır.

$arr = array('apple'=>'sweet','grapefruit'=>'bitter','
pear'=>'tasty','banana'=>'yellow');

doesn't mean that that the first element is 'apple'=>'sweet' and the last - 'banana'=>'yellow' just because you put 'apple' first and 'banana' last. Actually, 'apple'=>'sweet' will be the first and 'banana'=>'yellow' will be the second because of alphabetical ascending sort order.