How to remove similar entries from array php - php

So i have array like this and sometimes it has very similar entries:
Array
(
[0] => greys anatomy
[1] => element 3d
[2] => interstellar
[3] => monster ball
[4] => scorpion
[5] => taken 3
[6] => the flash
[7] => wild card
[8] => big bang theory
[9] => the big bang theory
[10] => fredrik kempe vincero
[11] => fredrik kempe vicero
)
I would like to remove similar entries that are longer ones. So for example in this array: [9] => the big bang theory and [10] => fredrik kempe vincero entries should be removed. as they are similar to 8th and 11th entry, but longer.
EDIT:
So if anyone needs, I made working solution out of two answers below:
function check_similar($first, $second)
{
similar_text($first, $second, $percent);
if ($percent >= 80) { //needed percent value
return true;
}
else {
return false;
}
}
for ($i = 0; $i < count($array); $i++) {
for ($j = $i; $j < count($array); $j++) {
if ($j > $i && check_similar($array[$i],$array[$j]) == true) {
$array[$j] = null;
}
}
}
// filter array to remove null values and reindex
$array = array_values(array_filter($array));
print_r($array);

String similarity is a very difficoult problem that cannot be solved easily. There are several complex approaches, but none can be effective as if it was made by a human being.
Take a look on php soundhex and levenshtein which could be an easy solution for your particular case.
In any case, given a custom function that defines or not if a string is similar to another, to make your array unique you have to do something like:
// set to null all subsequent similar strings
for ($i = 0; $i < count($array); $i++) {
for ($j = $i; $j < count($array); $j++) {
if ($j > $i && similar($array[$i],$array[$j])) {
$array[$j] = null;
}
}
}
// filter array to remove null values
$array = array_filter($array);

Take a look at the similar_text function.
similar_text('the big bang theory','big bang theory', $percent);
echo $percent; // 88%
This is obviously more difficult than it seems, but can do this check while making this array.
See this link for an alternate implementation.

Related

Sorting an array of numbers with for-loop

I have a task of sorting an array of numbers in both ascending and descending order. The challenge is, I can't use the built-in sort function, but loop through the array with for-loops instead.
I am a total newbie when it comes to PHP and this task straight off baffles me. Here is the code I'm supposed to work with:
<?php
$arr = $_GET['arr'];
$table = explode(',', $arr);
$count = count($table);
// What I tried to work with, didn't get to work:
for ($i = 0; $i < $count; $i++) {
for ($j = $i + 1; $j < $count; $j++) {
if ($table[$i] > $table[$j]) {
$temp = $table[$i];
$table[$i] = $table[$j];
$table[$j] = $temp;
$asc = implode("," $temp);
}
}
}
echo "Ascending: $asc";
echo "Descending: $desc";
?>
Any clue why this doesn't run? At some point, I got the first (largest) number in the array with the echo, but don't really know what broke that either.
Move the line
$asc = implode(",", $table);
from its current location below the outer for loop and maybe add the line
$desc = implode(",", array_reverse($table));
to get the descending sort order.
Many ways to make it. One solution you will find in the code below. you will certainly notice that the sorting depends only on one operator. Therefore, you can build a function out of it by specifying the sorting as a parameter. function(array $array, string $sort) {}
DESC
$arr= array(112,21,130,140,2,42);
for($i=0; $i<count($arr)-1; $i++)
{
for($j=0; $j<count($arr)-1; $j++)
{
if($arr[$j] < $arr[$j+1]){
$temp= $arr[$j+1];
$arr[$j+1]= $arr[$j];
$arr[$j]= $temp;
}
}
}
print_r($arr);
Output:
Array
(
[0] => 140
[1] => 130
[2] => 112
[3] => 42
[4] => 21
[5] => 2
)
ASC
$arr= array(112,21,130,140,2,42);
for($i=0; $i<count($arr)-1; $i++)
{
for($j=0; $j<count($arr)-1; $j++)
{
if($arr[$j] > $arr[$j+1]){
$temp= $arr[$j+1];
$arr[$j+1]= $arr[$j];
$arr[$j]= $temp;
}
}
}
print_r($arr);
Output
Array
(
[0] => 2
[1] => 21
[2] => 42
[3] => 112
[4] => 130
[5] => 140
)

Sorting an array with bubble sort [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 3 years ago.
I am trying to create an algorithm that shows each step of bubble sort, sorting one number at a time. I was was able to sort the number at the first index, but I need to figure out how to sort all the numbers.
$x = array (9,7,5,3,0);
$count = count($x);
for($i = 0; $i < $count-1; $i++ ) {
$temp = $x[$i+1];
$x[$i+1] = $x[$i];
$x[$i] = $temp;
echo '<pre>';
print_r($x);
}
My current output is:
Array
(
[0] => 7
[1] => 9
[2] => 5
[3] => 3
[4] => 0
)
Array
(
[0] => 7
[1] => 5
[2] => 9
[3] => 3
[4] => 0
)
Array
(
[0] => 7
[1] => 5
[2] => 3
[3] => 9
[4] => 0
)
Array
(
[0] => 7
[1] => 5
[2] => 3
[3] => 0
[4] => 9
)
From here I need to continue sorting the remaining numbers. For 7, the output should be
57390
53790
53970
53907
and then for 3
35079
30579
30759
30795
and then for 0, it should be same for all 4 lines like
03570
03579
03579
03579
[The assigned problem.][1]
Two issues:
You should only swap values when they are not in the right order
You need an outer loop to repeat this inner loop, similar to a proper bubble sort algorithm.
Your code can be modified like below so it generates the required output:
$x = array (9,7,5,3,0);
$count = count($x) - 1;
for($times = 0; $times < $count; $times++) {
for($i = 0; $i < $count; $i++ ) {
$temp = $x[$i+1];
if ($temp < $x[$i]) {
$x[$i+1] = $x[$i];
$x[$i] = $temp;
}
echo implode(" ", $x) . "\n";
}
echo "\n";
}
Note that a proper bubble sort algorithm will perform fewer iterations.
Bubble sort is basically simplified into a min() + shift (or sometimes swap) operation that occurs N times. So it's an O(n^2) algorithm.
Since this is for learning purposes I'm going to try to be as verbose as possible.
function getMin(Array &$array): Int {
$min = reset($array);
$minKey = null;
// Find the minimum value
foreach($array as $k => $n) {
if ($n < $min) {
$min = $n;
$minKey = $k;
}
}
// remove the minimum value from the array
$array[$k] = null;
$array = array_filter($array, function ($v) { return $v !== null; });
return $min;
}
$array = [9,7,5,3,0];
foreach ($array as $n => $value) {
// Find the min value in the array from Nth index onward
$min = getMin($array); // get the smallest value in the array and remove it.
$sorted[] = $min; // push it on to the new array
}
var_dump($sorted);
This gives you the expect result:
array(5) {
[0]=>
int(0)
[1]=>
int(3)
[2]=>
int(5)
[3]=>
int(7)
[4]=>
int(9)
}
Of course, this is not the way you would want to implement Bubble Sort, because it's a bit circuitous. Again, it's for educational purposes. You can inspect the $array as it's being modified at each step and the new $sorted as it's being built. Typically you would just swap the min/max values in place and use the same array (keeping track of the keys to rescan the array).
Like this...
// Unsorted $array
$array = [9,7,5,3,0];
// Sort the array
for ($lastKey = $i = 0, $len = count($array); $i < $len; $i++) {
// Scan for minimum value
for ($minKey = $j = $lastKey, $min = $array[$minKey]; $j < $len; $j++) {
if ($array[$j] < $min) {
$minKey = $j;
$min = $array[$j];
}
}
// Swap the values
$swap = $array[$lastKey];
$array[$lastKey] = $min;
$array[$minKey] = $swap;
// Update the scan position
$lastKey++;
}
var_dump($array); // Gives you [0,3,5,7,9]
You are performing unconditional position swapping, but you actually need to check if movement is required.
There is no shortage of tutorials that demonstrate a bubble sort in php. A quick good lead me to this one: https://www.w3resource.com/php-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-6.php which can be modified for your purposes.
PHP now offers "array destructuring" which means you no longer need to use a temporary holding variable while swapping.
Code: (Demo)
$x = [9,7,5,3,0];
$count = count($x) - 1;
for ($pass = 0; $pass < $count; ++$pass) {
for ($i = 0; $i < $count; ++$i) {
if ($x[$i] > $x[$i + 1]) {
[$x[$i + 1], $x[$i]] = [$x[$i], $x[$i + 1]];
}
$results[] = implode($x);
}
$results[] = "\n";
}
echo implode("\n", $results);

sorting array without php built-in sort function

I am very newbie on programming, first studying PHP language about arrays. I can sort an array with sort function, but I got stuck here.
If i have input array(1,3,5,6,7,8,11,12,17,11)
I try to get output 12 or bigger number 2, but if I do print_r($array[i] - 1);
I just get 10-1=9. how can i get value 12?
and then if I have input array(1,2,3,5,6) I try to get output false because of the missing number 4.
I make sort function:
for(int j:0;j<=count($array) ;j++) {
for(int i:0;i<=count($array[i+1]);i++{
if($array[i]>$array[$+1]{
$temp=$array[$i+1];
$array[$i+1]=$array[$i];
$array[$i]=temp;
}
}
}
print_r($array) ;
Thanks if someone can help me or teach me? :)
You have a lot of syntax errors in your code. Check the comments under your question, they pretty much covered it.
To sort an array with a custom sort you can use this:
$array = array(1,3,5,6,7,8,11,12,17,11);
$arrayCount = count($array); // no need to evaluate the count on every iteration of the for loop
for($i=0; $i < $arrayCount - 1; $i++)
{
for($j = $i+1; $j < $arrayCount; $j++)
{
// if you want the array sorted from bigger to smaller number use `>` here
if($array[$j] < $array[$i])
{
$temp = $array[$i];
$array[$i] = $array[$j];
$array[$j] = $temp;
}
}
}
print_r($array);
which outputs:
Array
(
[0] => 1
[1] => 3
[2] => 5
[3] => 6
[4] => 7
[5] => 8
[6] => 11
[7] => 11
[8] => 12
[9] => 17
)
Now to retrieve a desired value from the array or false if it does not exist you would write something like this using the built in array_search() method:
// Check if array contains a value 12, if it does return the index location in the array
// returns false if the value is not found
$index = array_search(12, $array);
if($index === false)
{
echo 'Value does not exist in the array.';
}
else
{
echo 'Value '.$array[$index].' is at index '.$index.' in the array.';
}

Find total year spans in an array with gaps

I need to draw a stacked bar graph for this array which should have 2 bars separated with a white-space of 2 years span (from year 1998 to 2000)
The Problem:
the first bar should be like,
*1998-1997* - *2 years gap* - *2000-2008*
The bars should merge shorter year-spans within like it did in taking 2000 from array0 and 2008 from array 1
Array
(
[comp_name] => C++
[parent_cat_name] => Information Technology
[sub_cat_name] => Programming
[total_years] => 6
[last_year] => 2006
[start_year] => 2000
)
Array
(
[comp_name] => .NET
[parent_cat_name] => Information Technology
[sub_cat_name] => Programming
[total_years] => 7
[last_year] => 2008
[start_year] => 2001
)
Array
(
[comp_name] => API
[parent_cat_name] => Information Technology
[sub_cat_name] => Programming
[total_years] => 1
[last_year] => 1998
[start_year] => 1997
)
You want to merge two array items, if they are adjacent according to some condition AND have some equality condition on some other fields.
You might do:
for(;;)
{
$merge = array();
$n = count($data);
for ($i = 0; empty($merge) && $i < $n-1; $i++)
{
for ($j = $i+1; empty($merge) && $j < $n; $j++)
{
// Are $i and $j congruent?
if ($data[$i]['parent_cat_name'] != $data[$j]['parent_cat_name'])
continue;
if ($data[$i]['sub_cat_name'] != $data[$j]['sub_cat_name'])
continue;
// Are $i and $j adjacent?
if ($data[$i]['last_year']+1 == $data[$j]['start_year'])
{
$merge = array($i, $j);
break;
}
if ($data[$j]['last_year']+1 == $data[$i]['start_year'])
$merge = array($j, $i);
break;
}
// They are congruent but not adjacent, try the next
}
}
// If we get to the end and find nothing mergeable, exit.
if (empty($merge))
break;
list($i, $j) = $merge;
// We add $j to $i
$data[$i]['last_year'] = $data[$j]['last_year']
$data[$i]['total_years'] += $data[$j]['total_years']
// We destroy $j
unset($data[$j]);
// Dirty renumber
$data = array_values($data);
// Now data has been modified, let's do this again.
}

Checking if a number in an array divides another number in the same array

What I need to accomplish is,
I have an array, 2 3 4 5 6 7 8 9 10
I need to check if any numbers in the array divides any other number in the array perfectly. (%=0) If yes, unset the the number.
Its over my head and I cant get it working and everything I tried gives me infinite loops and its making me ill. (lol)
I am not including any codes, because all I could come up with is a nested forloop which doesnt work :(
So here is a sample :
Input array :2 3 4 5 6 7 8
Output = 5 6 7 8
Any idea guys?
UPDATE:
Cracked the nut myself with bit more debugging. (Incase if that can be helpful for someone in future.)
// use array_unique, array_values and $size = sizeof($array)
for ($i = 0; $i < $size; $i++)
{
for ($j = $size - 1; $j > $i; $j--)
if ($numbers[$j] % $numbers[$i] == 0)
{
unset($numbers[$i]);
break;
}
}
I will not do this in real code, just because I think you want to do that yourself.
LoopA iterating the intput array:
LoopB iterating the input array:
check division of loopA value and loopB value, and add the value of loopA to a new array accordingly
End loopB
End loopA
Print the new array
Note: This is not complete, but it certainly should give you a start on how to continue.
For sorted ordered number
$arr = array(2,3,4,5,6,7,8,9,10,11,12,13,14);
$half_c = ceil(count($arr)/2) - 1;
$result_array = array_slice($arr, $half_c);
Edit: For random array you can cut half again, and iterate only first part of array. Prime number theory also can help to write faster algorithm for first part of array.
How about:
$arr = range(2,20);
$size = count($arr);
for ($i=0; $i<$size; $i++) {
for ($j=$size-1; $j>$i; $j--) {
if ($arr[$j]%$arr[$i]) continue;
unset($arr[$i]);
break;
}
}
print_r($arr);
output:
Array
(
[9] => 11
[10] => 12
[11] => 13
[12] => 14
[13] => 15
[14] => 16
[15] => 17
[16] => 18
[17] => 19
[18] => 20
)
Try this:
for($i = 0; $i < count($arr); $i++)
{
for($j = 0; $j < count($arr); $j++)
{
if($arr[$i] != $arr[$j] && $arr[$i] % $arr[$j] === 0)
{
unset($arr[$j);
break;
}
}
}

Categories