Hızlı vaka sayımı

7 Cevap php

Ben php işlemek için dizeleri çok sayıda var. Ben (ucwords(strtolower($str)) kullanılarak) başlık durumda olması onları "düzeltmek" istiyorum ama onlar zaten tüm üst veya küçük harf yalnızca. Onlar zaten karışık durumda iseniz, ben sadece yerine sadece oldukları gibi onları terk ediyorum.

Bu kontrol etmek için en hızlı yolu nedir? Bu for dize yoluyla ing bu konuda gitmek için oldukça yavaş bir yol olacak gibi görünüyor.

Burada çok yavaş olacağını düşünüyorum, ben ne var:

function fixCase($str)
{
	$uc = 0;
	$lc = 0;
	for($i=0;$i<strlen($str);$i++)
	{
		if ($str[$i] >= 'a' && $str[$i] <= 'z')
			$lc++;
		else if ($str[$i] >= 'A' && $str[$i] <= 'Z')
			$uc++;
	}

	if ($uc == 0 || $lc == 0)
	{
		return ucwords(strtolower($str));
	}
}

7 Cevap

sadece (küçük harf duyarlı) karşılaştırmak bir dize kullanın

function fixCase($str)
{
  if ( 
       (strcmp($str, strtolower($str)) === 0) || 
       (strcmp($str, strtoupper($str)) === 0) ) 
  {
    $str = ucwords(strtolower($str));
  }

  return $str;
}

Sorunun doğası gereği her karakterin bakmak gerekir, çünkü herhangi bir şaşırtıcı optimizasyon orada olacak değil.

Şahsen, algoritmanın bu tür dize karakterler üzerinde sadece döngü olur:

  • , Dize ilk karaktere bakıp o büyük veya küçük harf olup olmadığını gösteren bir değişken.
  • Şimdi her karakter sırayla inceleyelim. Eğer dizenin sonuna kadar almak ve hepsi ilk karakter olarak aynı durumda oldum, sizin gibi dize'nın durumda düzeltmek.
  • any karakter ilk karakter farklı bir durumda olduğunu, döngü kırmak ve dize döndürür.


Edit: gerçek kod, seni almak için gidiyoruz gibi bu yaklaşık olarak iyi olduğunu düşünüyorum.

// returns 0 if non-alphabetic char, 1 if uppercase, 2 if lowercase
function getCharType($char)
{
    if ($char >= 'A' && $char <= 'Z')
    {
        return 1;
    }
    else if ($char >= 'a' && $char <= 'z')
    {
        return 2;
    }
    else
    {
        return 0;
    }
}

function fixCase($str)
{
    for ($i = 0; $i < strlen($str); $i++)
    {
        $charType = getCharType($str[$i]);
        if ($charType != 0)
        {
            $firstCharType = $charType;
            break;
        }
    }

    for ($i = $i + 1; $i < strlen($str); $i++)
    {
        $charType = getCharType($str[$i]);
        if ($charType != $firstCharType && $charType != 0)
        {
            return $str;
        }
    }

    if ($firstCharType == 1) // uppercase, need to convert to lower first
    {
        return ucwords(strtolower($str));
    }
    else if ($firstCharType == 2) // lowercase, can just ucwords() it
    {
        return ucwords($str);
    }
    else // there were no letters at all in the string, just return it
    {
        return $str;
    }
}

Ben yayınlanmıştır dize durumu test fonksiyonunu deneyebilirsiniz here

function getStringCase($subject)
{
    if (!empty($subject))
    {
        if (preg_match('/^[^A-Za-z]+$/', $subject))
            return 0;   // no alphabetic characters
        else if (preg_match('/^[^A-Z]+$/', $subject))
            return 1;   // lowercase
        else if (preg_match('/^[^a-z]+$/', $subject))
            return 2;   // uppercase
        else
            return 3;   // mixed-case
    }
    else
    {
        return 0;   // empty
    }
}

Eğer sabitleme zaten karışık durumda dizeleri önlemek istiyorsanız neden verimlilik için o zaman büyük olasılıkla zaman harcıyorsun ise, bugünkü durum ne olursa olsun, her dizeyi dönüştürmek:

function fixCase($str)
{
    return ucwords(strtolower($str));
}

Bu dizeleri genellikle başlık halinde isterim olanların uzunluğu için kabul edilen yanıt dışında herhangi yavaş koştu ise çok sürpriz olacak, ve bu konuda endişelenmenize gerek bir daha az bir durum.

Ancak, kasa bazı amaçlanan anlam korumak istiyorsanız örneğin, zaten karışık durumda dizeleri dönüştürme önlemek için iyi bir neden varsa, o zaman evet, jcinacio cevabı kesinlikle basit ve çok etkili.

Bu dize = küçük (string) veya dize = büyük (string) ve eğer öyleyse o zaman bırakmak olmadığını kontrol etmek kolay olmaz. Aksi takdirde işlemi gerçekleştirin.

Evet bir şimdiye kadar 2 önerilen cevapları testi ve benim özgün çözüm yapmaya karar verdi. Ben sonuçlar bu şekilde dışarı çıkarmak düşündüm olmazdı, ama ben doğal yöntemler / o / çok daha hızlı her yerinde vardır sanırım.

Kod:

function method1($str)
{
	if (strcmp($str, strtolower($str)) == 0)
	{
		return ucwords($str);
	}
	else if (strcmp($str, strtoupper($str)) == 0)
	{
		return ucwords(strtolower($str));
	}
	else
	{
		return $str;
	}
}

// returns 0 if non-alphabetic char, 1 if uppercase, 2 if lowercase
function getCharType($char)
{
	if ($char >= 'A' && $char <= 'Z')
	{
	    return 1;
	}
	else if ($char >= 'a' && $char <= 'z')
	{
	    return 2;
	}
	else
	{
	    return 0;
	}
}

function method2($str)
{
	for ($i = 0; $i < strlen($str); $i++)
	{
	    $charType = getCharType($str[$i]);
	    if ($charType != 0)
	    {
	        $firstCharType = $charType;
	        break;
	    }
	}

	for ($i = $i + 1; $i < strlen($str); $i++)
	{
	    $charType = getCharType($str[$i]);
	    if ($charType != $firstCharType && $charType != 0)
	    {
	        return $str;
	    }
	}

	if ($firstCharType == 1) // uppercase, need to convert to lower first
	{
	    return ucwords(strtolower($str));
	}
	else if ($firstCharType == 2) // lowercase, can just ucwords() it
	{
	    return ucwords($str);
	}
	else // there were no letters at all in the string, just return it
	{
	    return $str;
	}
}

function method0($str)
{
	    $uc = 0;
	    $lc = 0;
	    for($i=0;$i<strlen($str);$i++)
	    {
	            if ($str[$i] >= 'a' && $str[$i] <= 'z')
	                    $lc++;
	            else if ($str[$i] >= 'A' && $str[$i] <= 'Z')
	                    $uc++;
	    }

	    if ($uc == 0 || $lc == 0)
	    {
	            return ucwords(strtolower($str));
	    }
}


function test($func,$s)
{
	$start = gettimeofday(true);
	for($i = 0; $i < 1000000; $i++)
	{
		$s4 = $func($s);
	}
	$end = gettimeofday(true);
	echo "$func Time: " . ($end-$start) . " - Avg: ".sprintf("%.09f",(($end-$start)/1000000))."\n";
}


$s1 = "first String";
$s2 = "second string";
$s3 = "THIRD STRING";

test("method0",$s1);
test("method0",$s2);
test("method0",$s3);

test("method1",$s1);
test("method1",$s2);
test("method1",$s3);

test("method2",$s1);
test("method2",$s2);
test("method2",$s3);

Sonuçlar:

method0 Time: 19.2899270058 - Avg: 0.000019290
method0 Time: 20.8679389954 - Avg: 0.000020868
method0 Time: 24.8917310238 - Avg: 0.00002489	
method1 Time: 3.07466816902 - Avg: 0.000003075
method1 Time: 2.52559089661 - Avg: 0.000002526
method1 Time: 4.06261897087 - Avg: 0.000004063
method2 Time: 19.2718701363 - Avg: 0.000019272
method2 Time: 35.2485661507 - Avg: 0.000035249
method2 Time: 29.3357679844 - Avg: 0.000029336

Kısa sürede aksanlı veya çift nokta koymak karakterler vardır gibi yanlış olacaktır [AZ] sadece bakar şeyi unutmayın. Sonuç yanlış ise hız için optimize (sonuç doğru olmak zorunda yoksa hey, bu ... Eğer gerçekten hızlı uygulama yazabilirsiniz) anlamsızdır