টেট্রিস-এ অ্যারে


99

নিম্নলিখিত অ্যারে বিবেচনা করুন:

/www/htdocs/1/sites/lib/abcdedd
/www/htdocs/1/sites/conf/xyz
/www/htdocs/1/sites/conf/abc/def
/www/htdocs/1/sites/htdocs/xyz
/www/htdocs/1/sites/lib2/abcdedd

সাধারণ বেস পাথ সনাক্ত করার সবচেয়ে সংক্ষিপ্ত এবং সর্বাধিক মার্জিত উপায় কী - এই ক্ষেত্রে

/www/htdocs/1/sites/

এবং অ্যারে সমস্ত উপাদান থেকে এটি অপসারণ?

lib/abcdedd
conf/xyz
conf/abc/def
htdocs/xyz
lib2/abcdedd

4
এটি চেষ্টা করার মতো হতে পারে: en.wikibooks.org/wiki/Algorithm_implementation/Strings/… (আমি এটি চেষ্টা করেছি এবং এটি কাজ করে)।
রিচার্ড নপ

4
ওহউ! এরকম অনেক উজ্জ্বল ইনপুট। আমি আমার সমস্যাটি সমাধানের জন্য একটি গ্রহণ করব, তবে আমি অনুভব করি যে সত্যিকার অর্থে গ্রহণযোগ্য উত্তর গৃহীত করার জন্য, সমাধানগুলির তুলনা করতে হবে। আমি এটি করতে কাছাকাছি না হওয়া পর্যন্ত এটি একটি সময় নিতে পারে, তবে আমি অবশ্যই করব।
পেক্কা

বিনোদনমূলক শিরোনাম: ডি বিটিডাব্লু: কেন আমি আপনাকে মনোনীত মডারেটরের তালিকায় খুঁজে পাচ্ছি না? @ পেপকা
সূরিকান

4
দুই বছরের জন্য কোন গ্রহণযোগ্য উত্তর?
গর্ডন

4
@ পেক্কা এর তিন বছরের কাছাকাছি যাওয়ায় এর কোনও গ্রহণযোগ্য উত্তর নেই :( এবং এটি এমন এক দুর্দান্ত শিরোনাম যা আমি এক মুহূর্ত আগে এটি মনে রেখেছিলাম এবং "একটি অ্যারে টেট্রিসিং" গোগলড করেছি
ক্যামিলো মার্টিন

উত্তর:


35

longest_common_prefixইনপুট হিসাবে দুটি স্ট্রিং লাগে এমন একটি ফাংশন লিখুন । তারপরে এটিকে স্ট্রিংগুলিতে তাদের সাধারণ উপসাগুলিতে হ্রাস করার জন্য প্রয়োগ করুন। যেহেতু এটি সাহচর্যমূলক এবং পরিবর্তনমূলক হয় আদেশ ফলাফলের জন্য কোনও বিষয় নয়।

এটি অন্যান্য বাইনারি অপারেশনগুলির মতো একই উদাহরণস্বরূপ সংযোজন বা সর্বশ্রেষ্ঠ সাধারণ বিভাজক।


8
+1 প্রথম 2 টি স্ট্রিং তুলনা করার পরে, 3 য় স্ট্রিং এবং এর সাথে তুলনা করতে ফলাফল (সাধারণ পাথ) ব্যবহার করুন।
মিলান বাবুস্কভ

23

এগুলি একটি ত্রি ডাটা স্ট্রাকচারে লোড করুন। পিতা বা মাতা নোড থেকে শুরু করে দেখুন যে কোনও একটিতে বাচ্চাদের গণনা করা হচ্ছে। আপনি যখন সেই ম্যাজিক নোডটি খুঁজে পান, কেবলমাত্র প্যারেন্ট নোড কাঠামোটি ভেঙে ফেলুন এবং বর্তমান নোডটি রুট হিসাবে থাকবে।


10
আপনি যে ট্রাই ট্রি কাঠামোর ডেটা লোড করেন সেই অপারেশনটিতে দীর্ঘতম সাধারণ উপসর্গটি সন্ধান করার জন্য অ্যালগরিদমকে অন্তর্ভুক্ত করা হবে না, এইভাবে গাছের কাঠামোটি ব্যবহার অপ্রয়োজনীয় করে তোলে? অর্থাত্ যখন গাছ তৈরির সময় আপনি এটি সনাক্ত করতে পারতেন কেন একাধিক শিশুদের জন্য গাছটি পরীক্ষা করুন। তাহলে কেন মোটেও একটা গাছ? মানে আপনি যদি ইতিমধ্যে একটি অ্যারে দিয়ে শুরু করেন। আপনি যদি অ্যারেগুলির পরিবর্তে কেবল ট্রাই ব্যবহার করে স্টোরেজটি পরিবর্তন করতে পারেন তবে আমার ধারণা এটি বোধগম্য।
বেন শ্বেইন

4
আমি মনে করি আপনি যদি সাবধান হন তবে আমার সমাধানটি ট্রাই তৈরির চেয়ে বেশি দক্ষ।
স্টার ব্লু

এই উত্তরটি ভুল। আমার এবং অন্যান্য উত্তরগুলিতে তুচ্ছ সমাধান পোস্ট করা আছে যা হে (এন)।
অরি রোনেন

@ এল.পেস্ক্যাডো: সবচেয়ে খারাপ ক্ষেত্রে উত্সের স্ট্রিংয়ের দৈর্ঘ্যের সাথে চেষ্টাগুলি চতুর্ভুজ আকারের হয়।
বিলি ওনিল

10
$common = PHP_INT_MAX;
foreach ($a as $item) {
        $common = min($common, str_common($a[0], $item, $common));
}

$result = array();
foreach ($a as $item) {
        $result[] = substr($item, $common);
}
print_r($result);

function str_common($a, $b, $max)
{
        $pos = 0;
        $last_slash = 0;
        $len = min(strlen($a), strlen($b), $max + 1);
        while ($pos < $len) {
                if ($a{$pos} != $b{$pos}) return $last_slash;
                if ($a{$pos} == '/') $last_slash = $pos;
                $pos++;
        }
        return $last_slash;
}

এটি এখন পর্যন্ত পোস্ট করা সেরা সমাধান, তবে এর উন্নতি প্রয়োজন। এটা তোলে একাউন্টে পূর্ববর্তী দীর্ঘতম সাধারণ পথ নেয়নি (সম্ভবত প্রয়োজনীয় তুলনায় স্ট্রিং এর উপর আরো বেশি iterating), এবং একাউন্টে পাথ নেননি (তাই /usr/libএবং /usr/lib2এটি দিয়েছে /usr/libদীর্ঘতম সাধারণ পাথ হিসাবে বদলে /usr/)। আমি (আশা করি) দুটোই ঠিক করে রেখেছি।
গাবে

7

ভাল, বিবেচনা করে আপনি XORস্ট্রিংয়ের সাধারণ অংশগুলি খুঁজতে এই পরিস্থিতিতে ব্যবহার করতে পারেন । আপনি যে কোনও সময় দুটি বাইট একইরূপে xor করলে আপনি আউটপুট হিসাবে নালবাইট পাবেন। সুতরাং আমরা এটি আমাদের সুবিধার জন্য ব্যবহার করতে পারি:

$first = $array[0];
$length = strlen($first);
$count = count($array);
for ($i = 1; $i < $count; $i++) {
    $length = min($length, strspn($array[$i] ^ $first, chr(0)));
}

সেই একক লুপের পরে, $lengthপরিবর্তনশীল স্ট্রিংগুলির অ্যারের মধ্যে দীর্ঘতম সাধারণ বেস পার্টের সমান। তারপরে, আমরা প্রথম উপাদানটি থেকে সাধারণ অংশটি বের করতে পারি:

$common = substr($array[0], 0, $length);

এবং সেখানে আপনি এটা আছে। একটি ফাংশন হিসাবে:

function commonPrefix(array $strings) {
    $first = $strings[0];
    $length = strlen($first);
    $count = count($strings);
    for ($i = 1; $i < $count; $i++) {
        $length = min($length, strspn($strings[$i] ^ $first, chr(0)));
    }
    return substr($first, 0, $length);
}

মনে রাখবেন যে এটি একাধিক পুনরাবৃত্তি ব্যবহার করে তবে সেই পুনরাবৃত্তিগুলি গ্রন্থাগারগুলিতে করা হয়, সুতরাং ব্যাখ্যামূলক ভাষায় এটির বিশাল দক্ষতা লাভ হবে ...

এখন, আপনি যদি কেবলমাত্র পুরো পথ চান, আমাদের শেষ /চরিত্রটি ছাঁটাই করতে হবে । সুতরাং:

$prefix = preg_replace('#/[^/]*$', '', commonPrefix($paths));

এখন, এটা মাত্রাতিরিক্ত যেমন দুটি স্ট্রিং কাটা পারে /foo/barএবং /foo/bar/bazকরার কাটা হবে /foo। কিন্তু তা নির্ধারণ করতে অন্য পুনরাবৃত্তির বৃত্তাকার যোগ করার সংক্ষিপ্ত যদি পরবর্তী অক্ষরে পারেন হয় / বা শেষ অফ স্ট্রিং, আমি যে কাছাকাছি একটি উপায় দেখতে পাচ্ছি না ...


3

একটি নিষ্কলুষ পন্থা হবে /অ্যারেগুলির প্রতিটি উপাদানকে তুলনামূলকভাবে পরের দিকে পাথগুলি বিস্ফোরিত করা । সুতরাং যেমন প্রথম উপাদানটি সমস্ত অ্যারেতে খালি থাকবে, সুতরাং এটি মুছে ফেলা হবে, পরবর্তী উপাদানটি হবে www, এটি সমস্ত অ্যারেতে একই রকম, তাই এটি সরানো হয় ইত্যাদি ইত্যাদি etc.

কিছুটা এইরকম (অরক্ষিত)

$exploded_paths = array();

foreach($paths as $path) {
    $exploded_paths[] = explode('/', $path);
}

$equal = true;
$ref = &$exploded_paths[0]; // compare against the first path for simplicity

while($equal) {   
    foreach($exploded_paths as $path_parts) {
        if($path_parts[0] !== $ref[0]) {
            $equal = false;
            break;
        }
    }
    if($equal) {
        foreach($exploded_paths as &$path_parts) {
            array_shift($path_parts); // remove the first element
        }
    }
}

এরপরে আপনাকে $exploded_pathsআবার উপাদানগুলিকে আবার প্রবেশ করতে হবে:

function impl($arr) {
    return '/' . implode('/', $arr);
}
$paths = array_map('impl', $exploded_paths);

যা আমাকে দেয়:

Array
(
    [0] => /lib/abcdedd
    [1] => /conf/xyz
    [2] => /conf/abc/def
    [3] => /htdocs/xyz
    [4] => /conf/xyz
)

এটি ভাল স্কেল নাও করতে পারে;)


3

ঠিক আছে, আমি নিশ্চিত নই যে এটি বুলেট-প্রুফ, তবে আমি মনে করি এটি কার্যকর হয়:

echo array_reduce($array, function($reducedValue, $arrayValue) {
    if($reducedValue === NULL) return $arrayValue;
    for($i = 0; $i < strlen($reducedValue); $i++) {
        if(!isset($arrayValue[$i]) || $arrayValue[$i] !== $reducedValue[$i]) {
            return substr($reducedValue, 0, $i);
        }
    }
    return $reducedValue;
});

এটি রেফারেন্স স্ট্রিং হিসাবে অ্যারেতে প্রথম মানটি নেবে। তারপরে এটি রেফারেন্স স্ট্রিংটিতে পুনরাবৃত্তি হবে এবং প্রতিটি চরকে একই পজিশনে দ্বিতীয় স্ট্রিংয়ের চরের সাথে তুলনা করবে। যদি কোনও চরিত্র মেলে না, তবে রেফারেন্স স্ট্রিংটি চরের অবস্থানের সাথে সংক্ষিপ্ত করা হবে এবং পরবর্তী স্ট্রিংটির তুলনা করা হবে। ফাংশনটি তারপরে সবচেয়ে সংক্ষিপ্ত মিলের স্ট্রিংটি ফিরিয়ে দেবে।

পারফরম্যান্স প্রদত্ত স্ট্রিংগুলির উপর নির্ভর করে। প্রারম্ভিক রেফারেন্সের স্ট্রিংটি সংক্ষিপ্ত হওয়ার সাথে সাথেই কোডটি দ্রুত শেষ হবে। যদিও এটি একটি সূত্রে কীভাবে রাখবেন তা আমার সত্যিই কোনও ধারণা নেই।

আমি দেখতে পেয়েছি যে স্ট্রিংগুলি বাছাইয়ের জন্য আর্টেফ্যাক্টোর দৃষ্টিভঙ্গি কর্মক্ষমতা বৃদ্ধি করে। যুক্ত হচ্ছে

asort($array);
$array = array(array_shift($array), array_pop($array));

আগে array_reduceউল্লেখযোগ্যভাবে কর্মক্ষমতা বৃদ্ধি করবে।

এছাড়াও মনে রাখবেন যে এটি দীর্ঘতম মিলে যাওয়া প্রাথমিক স্ট্রিংগুলিকে ফিরিয়ে দেবে , এটি আরও বহুমুখী তবে আপনাকে সাধারণ পথ দেবে না । আপনাকে দৌড়াতে হবে

substr($result, 0, strrpos($result, '/'));

ফলাফলের উপর এবং তারপরে আপনি ফলাফলগুলি মানগুলি সরাতে ব্যবহার করতে পারেন

print_r(array_map(function($v) use ($path){
    return str_replace($path, '', $v);
}, $array));

যা দেওয়া উচিত:

[0] => /lib/abcdedd
[1] => /conf/xyz/
[2] => /conf/abc/def
[3] => /htdocs/xyz
[4] => /lib2/abcdedd

মতামত স্বাগত।


3

আপনি প্রতিটি চরিত্রটি একবারে পড়ার জন্য দ্রুত উপসর্গটি সরিয়ে ফেলতে পারেন:

function findLongestWord($lines, $delim = "/")
{
    $max = 0;
    $len = strlen($lines[0]); 

    // read first string once
    for($i = 0; $i < $len; $i++) {
        for($n = 1; $n < count($lines); $n++) {
            if($lines[0][$i] != $lines[$n][$i]) {
                // we've found a difference between current token
                // stop search:
                return $max;
            }
        }
        if($lines[0][$i] == $delim) {
            // we've found a complete token:
            $max = $i + 1;
        }
    }
    return $max;
}

$max = findLongestWord($lines);
// cut prefix of len "max"
for($n = 0; $n < count($lines); $n++) {
    $lines[$n] = substr(lines[$n], $max, $len);
}

প্রকৃতপক্ষে, একটি চরিত্র-ভিত্তিক তুলনা দ্রুত হবে। অন্যান্য সমস্ত সমাধান "ব্যয়বহুল" অপারেটরগুলি ব্যবহার করে যা শেষ পর্যন্ত (একাধিক) অক্ষরের তুলনাও করে। এমনকি পবিত্র জোয়েলের শাস্ত্রে এটি উল্লেখ করা হয়েছিল !
জান ফ্যাব্রি

2

লিনিয়ার সময় জটিলতা না থাকার এতে সুবিধা রয়েছে; তবে বেশিরভাগ ক্ষেত্রেই বাছাই করা অবশ্যই বেশি সময় গ্রহণের কাজ করবে না।

মূলত, চতুর অংশটি (কমপক্ষে আমি এটির সাথে কোনও ত্রুটি খুঁজে পাই না) এখানে রয়েছে বাছাইয়ের পরে আপনাকে কেবল প্রথমের সাথে শেষের সাথে তুলনা করতে হবে।

sort($a);
$a = array_map(function ($el) { return explode("/", $el); }, $a);
$first = reset($a);
$last = end($a);
for ($eqdepth = 0; $first[$eqdepth] === $last[$eqdepth]; $eqdepth++) {}
array_walk($a,
    function (&$el) use ($eqdepth) {
        for ($i = 0; $i < $eqdepth; $i++) {
            array_shift($el);
        }
     });
$res = array_map(function ($el) { return implode("/", $el); }, $a);

2
$values = array('/www/htdocs/1/sites/lib/abcdedd',
                '/www/htdocs/1/sites/conf/xyz',
                '/www/htdocs/1/sites/conf/abc/def',
                '/www/htdocs/1/sites/htdocs/xyz',
                '/www/htdocs/1/sites/lib2/abcdedd'
);


function splitArrayValues($r) {
    return explode('/',$r);
}

function stripCommon($values) {
    $testValues = array_map('splitArrayValues',$values);

    $i = 0;
    foreach($testValues[0] as $key => $value) {
        foreach($testValues as $arraySetValues) {
            if ($arraySetValues[$key] != $value) break 2;
        }
        $i++;
    }

    $returnArray = array();
    foreach($testValues as $value) {
        $returnArray[] = implode('/',array_slice($value,$i));
    }

    return $returnArray;
}


$newValues = stripCommon($values);

echo '<pre>';
var_dump($newValues);
echo '</pre>';

অ্যারে পুনর্নির্মাণের জন্য একটি অ্যারে_ওয়াক ব্যবহার করে আমার মূল পদ্ধতিটির বৈকল্পিক সম্পাদনা করুন

$values = array('/www/htdocs/1/sites/lib/abcdedd',
                '/www/htdocs/1/sites/conf/xyz',
                '/www/htdocs/1/sites/conf/abc/def',
                '/www/htdocs/1/sites/htdocs/xyz',
                '/www/htdocs/1/sites/lib2/abcdedd'
);


function splitArrayValues($r) {
    return explode('/',$r);
}

function rejoinArrayValues(&$r,$d,$i) {
    $r = implode('/',array_slice($r,$i));
}

function stripCommon($values) {
    $testValues = array_map('splitArrayValues',$values);

    $i = 0;
    foreach($testValues[0] as $key => $value) {
        foreach($testValues as $arraySetValues) {
            if ($arraySetValues[$key] != $value) break 2;
        }
        $i++;
    }

    array_walk($testValues, 'rejoinArrayValues', $i);

    return $testValues;
}


$newValues = stripCommon($values);

echo '<pre>';
var_dump($newValues);
echo '</pre>';

সম্পাদনা

সর্বাধিক দক্ষ এবং মার্জিত উত্তর প্রদত্ত প্রত্যেকটির উত্তর থেকে ফাংশন এবং পদ্ধতি নেওয়া জড়িত


1

আমি explode/ এবং তারপরে মানগুলি array_intersect_assocসাধারণ উপাদানগুলি সনাক্ত করতে এবং অ্যারেতে সঠিক সংশ্লিষ্ট সূচক রয়েছে তা নিশ্চিত করতে ব্যবহার করব । ফলস্বরূপ অ্যারেটি সাধারণ পাথ উত্পাদন করতে পুনরায় সংযুক্ত করা যেতে পারে।

function getCommonPath($pathArray)
{
    $pathElements = array();

    foreach($pathArray as $path)
    {
        $pathElements[] = explode("/",$path);
    }

    $commonPath = $pathElements[0];

    for($i=1;$i<count($pathElements);$i++)
    {
        $commonPath = array_intersect_assoc($commonPath,$pathElements[$i]);
    }

    if(is_array($commonPath) return implode("/",$commonPath);
    else return null;
}

function removeCommonPath($pathArray)
{
    $commonPath = getCommonPath($pathArray());

    for($i=0;$i<count($pathArray);$i++)
    {
        $pathArray[$i] = substr($pathArray[$i],str_len($commonPath));
    }

    return $pathArray;
}

এটি অনির্ধারিত, তবে, ধারণাটি হ'ল $commonPathঅ্যারেটিতে কেবল কখনও কখনও সেই পথের উপাদান রয়েছে যা তার বিপরীতে তুলনা করা হয়েছে এমন সমস্ত পথ অ্যারেতে অন্তর্ভুক্ত রয়েছে। লুপটি সম্পূর্ণ হয়ে গেলে, সত্যটি পেতে আমরা কেবল এটির সাথে পুনরায় সংযুক্ত করি$commonPath

ফেলিক্স ক্লিং দ্বারা নির্দেশিত হিসাবে আপডেট করুন , array_intersectসাধারণ উপাদানগুলি রয়েছে তবে বিভিন্ন আদেশে পাথ বিবেচনা করবেন না ... এটি সমাধান করার জন্য, আমি array_intersect_assocপরিবর্তে ব্যবহার করেছিarray_intersect

পাশাপাশি অ্যারে থেকে সাধারণ পাথ (বা এটিতে টেট্রিস!) অপসারণের জন্য যুক্ত কোড আপডেট করুন


এটি সম্ভবত কাজ করবে না। বিবেচনা করুন /a/b/c/dএবং /d/c/b/a। একই উপাদান, বিভিন্ন পথ।
ফেলিক্স ক্লিং

@ ফেলিক্স ক্লিং আমি অ্যারে_ইন্টারসেক্ট_সোক ব্যবহার করতে আপডেট করেছি যা একটি সূচক চেকও সম্পাদন করে
ব্রেন্ডন বুলেন

1

কেবল স্ট্রিং তুলনা কোণ থেকে দেখলে সমস্যাটি সরল করা যায়। এটি সম্ভবত অ্যারে-বিভাজনের চেয়ে দ্রুত:

$longest = $tetris[0];  # or array_pop()
foreach ($tetris as $cmp) {
        while (strncmp($longest+"/", $cmp, strlen($longest)+1) !== 0) {
                $longest = substr($longest, 0, strrpos($longest, "/"));
        }
}

এটি কাজ করবে না উদাহরণস্বরূপ এই সেট অ্যারে ('/ www / htdocs / 1 / সাইট / কনফারেন্স / অ্যাবসি / ডিফ', '/ www / এইচটিডোকস / 1 / সাইট / এইচটিডোকস / এক্সআইজেড', '/ www / এইচটিডোকস / 1 / সাইটjj / lib2 / abcdedd ',)।
আর্টেফ্যাক্টো

@ আর্টেফ্যাক্টো: আপনি ঠিক বলেছেন। সুতরাং আমি তুলনা করে সর্বদা একটি পিছনের স্ল্যাশ "/" অন্তর্ভুক্ত করার জন্য কেবল এটি পরিবর্তন করেছি। এটিকে অস্পষ্ট করে তোলে।
মারিও

1

পাইথনের os.path.commonprefix(m)ব্যবহারগুলি অ্যালগরিদম ব্যবহারের কাজটি কি কার্যকর হবে?

def commonprefix(m):
    "Given a list of pathnames, returns the longest common leading component"
    if not m: return ''
    s1 = min(m)
    s2 = max(m)
    n = min(len(s1), len(s2))
    for i in xrange(n):
        if s1[i] != s2[i]:
            return s1[:i]
    return s1[:n]

ওহ, হ ... এমন কিছু

function commonprefix($m) {
  if(!$m) return "";
  $s1 = min($m);
  $s2 = max($m);
  $n = min(strlen($s1), strlen($s2));
  for($i=0;$i<$n;$i++) if($s1[$i] != $s2[$i]) return substr($s1, 0, $i);
  return substr($s1, 0, $n);
}

এর পরে আপনি সাধারণ উপসর্গের দৈর্ঘ্য সহ আরম্ভের অফসেট হিসাবে মূল তালিকার প্রতিটি উপাদানকে সাবস্ট্রিট করতে পারেন।


1

আমি আমার টুপিটি রিংয়ে ফেলে দেব ...

function longestCommonPrefix($a, $b) {
    $i = 0;
    $end = min(strlen($a), strlen($b));
    while ($i < $end && $a[$i] == $b[$i]) $i++;
    return substr($a, 0, $i);
}

function longestCommonPrefixFromArray(array $strings) {
    $count = count($strings);
    if (!$count) return '';
    $prefix = reset($strings);
    for ($i = 1; $i < $count; $i++)
        $prefix = longestCommonPrefix($prefix, $strings[$i]);
    return $prefix;
}

function stripPrefix(&$string, $foo, $length) {
    $string = substr($string, $length);
}

ব্যবহার:

$paths = array(
    '/www/htdocs/1/sites/lib/abcdedd',
    '/www/htdocs/1/sites/conf/xyz',
    '/www/htdocs/1/sites/conf/abc/def',
    '/www/htdocs/1/sites/htdocs/xyz',
    '/www/htdocs/1/sites/lib2/abcdedd',
);

$longComPref = longestCommonPrefixFromArray($paths);
array_walk($paths, 'stripPrefix', strlen($longComPref));
print_r($paths);

1

ঠিক আছে, এখানে ইতিমধ্যে কিছু সমাধান রয়েছে তবে এটি মজাদার ছিল:

$values = array(
    '/www/htdocs/1/sites/lib/abcdedd',
    '/www/htdocs/1/sites/conf/xyz',
    '/www/htdocs/1/sites/conf/abc/def', 
    '/www/htdocs/1/sites/htdocs/xyz',
    '/www/htdocs/1/sites/lib2/abcdedd' 
);

function findCommon($values){
    $common = false;
    foreach($values as &$p){
        $p = explode('/', $p);
        if(!$common){
            $common = $p;
        } else {
            $common = array_intersect_assoc($common, $p);
        }
    }
    return $common;
}
function removeCommon($values, $common){
    foreach($values as &$p){
        $p = explode('/', $p);
        $p = array_diff_assoc($p, $common);
        $p = implode('/', $p);
    }

    return $values;
}

echo '<pre>';
print_r(removeCommon($values, findCommon($values)));
echo '</pre>';

আউটপুট:

Array
(
    [0] => lib/abcdedd
    [1] => conf/xyz
    [2] => conf/abc/def
    [3] => htdocs/xyz
    [4] => lib2/abcdedd
)

0
$arrMain = array(
            '/www/htdocs/1/sites/lib/abcdedd',
            '/www/htdocs/1/sites/conf/xyz',
            '/www/htdocs/1/sites/conf/abc/def',
            '/www/htdocs/1/sites/htdocs/xyz',
            '/www/htdocs/1/sites/lib2/abcdedd'
);
function explodePath( $strPath ){ 
    return explode("/", $strPath);
}

function removePath( $strPath)
{
    global $strCommon;
    return str_replace( $strCommon, '', $strPath );
}
$arrExplodedPaths = array_map( 'explodePath', $arrMain ) ;

//Check for common and skip first 1
$strCommon = '';
for( $i=1; $i< count( $arrExplodedPaths[0] ); $i++)
{
    for( $j = 0; $j < count( $arrExplodedPaths); $j++ )
    {
        if( $arrExplodedPaths[0][ $i ] !== $arrExplodedPaths[ $j ][ $i ] )
        {
            break 2;
        } 
    }
    $strCommon .= '/'.$arrExplodedPaths[0][$i];
}
print_r( array_map( 'removePath', $arrMain ) );

এটি সূক্ষ্মভাবে কাজ করে ... মার্ক বেকারের অনুরূপ তবে str_replace ব্যবহার করে


0

সম্ভবত খুব নিখুঁত এবং দু: খিত কিন্তু এটি কাজ করে। আমি এই অ্যালগরিদম ব্যবহার করেছি :

<?php

function strlcs($str1, $str2){
    $str1Len = strlen($str1);
    $str2Len = strlen($str2);
    $ret = array();

    if($str1Len == 0 || $str2Len == 0)
        return $ret; //no similarities

    $CSL = array(); //Common Sequence Length array
    $intLargestSize = 0;

    //initialize the CSL array to assume there are no similarities
    for($i=0; $i<$str1Len; $i++){
        $CSL[$i] = array();
        for($j=0; $j<$str2Len; $j++){
            $CSL[$i][$j] = 0;
        }
    }

    for($i=0; $i<$str1Len; $i++){
        for($j=0; $j<$str2Len; $j++){
            //check every combination of characters
            if( $str1[$i] == $str2[$j] ){
                //these are the same in both strings
                if($i == 0 || $j == 0)
                    //it's the first character, so it's clearly only 1 character long
                    $CSL[$i][$j] = 1; 
                else
                    //it's one character longer than the string from the previous character
                    $CSL[$i][$j] = $CSL[$i-1][$j-1] + 1; 

                if( $CSL[$i][$j] > $intLargestSize ){
                    //remember this as the largest
                    $intLargestSize = $CSL[$i][$j]; 
                    //wipe any previous results
                    $ret = array();
                    //and then fall through to remember this new value
                }
                if( $CSL[$i][$j] == $intLargestSize )
                    //remember the largest string(s)
                    $ret[] = substr($str1, $i-$intLargestSize+1, $intLargestSize);
            }
            //else, $CSL should be set to 0, which it was already initialized to
        }
    }
    //return the list of matches
    return $ret;
}


$arr = array(
'/www/htdocs/1/sites/lib/abcdedd',
'/www/htdocs/1/sites/conf/xyz',
'/www/htdocs/1/sites/conf/abc/def',
'/www/htdocs/1/sites/htdocs/xyz',
'/www/htdocs/1/sites/lib2/abcdedd'
);

// find the common substring
$longestCommonSubstring = strlcs( $arr[0], $arr[1] );

// remvoe the common substring
foreach ($arr as $k => $v) {
    $arr[$k] = str_replace($longestCommonSubstring[0], '', $v);
}
var_dump($arr);

আউটপুট:

array(5) {
  [0]=>
  string(11) "lib/abcdedd"
  [1]=>
  string(8) "conf/xyz"
  [2]=>
  string(12) "conf/abc/def"
  [3]=>
  string(10) "htdocs/xyz"
  [4]=>
  string(12) "lib2/abcdedd"
}

:)


@ ডুমসডে আমার উত্তরে উইকিপিডিয়ায় একটি লিঙ্ক আছে ... মন্তব্য করার আগে প্রথমে এটি পড়ার চেষ্টা করুন।
রিচার্ড নপ

আমি মনে করি শেষ পর্যন্ত আপনি কেবল প্রথম দুটি পথের তুলনা করুন। আপনার উদাহরণে এটি কাজ করে তবে আপনি যদি প্রথম পথটি সরিয়ে ফেলেন তবে এটি /www/htdocs/1/sites/conf/একটি সাধারণ মিল হিসাবে মিলবে। এছাড়াও, অ্যালগরিদম স্ট্রিংয়ের যে কোনও জায়গায় শুরু হওয়া সাবস্ট্রিংগুলির সন্ধান করে, তবে এই প্রশ্নের জন্য আপনি জানেন যে আপনি অবস্থান 0 থেকে শুরু করতে পারেন, এটি এটি আরও সহজ করে তোলে।
জান ফ্যাব্রি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.