How to decode from an unknown encoding in PHP? - php

My question is different from this one. I am trying to fix a broken encoding but I don't know how to proceed.
In my database I have this name:
mysql> select filename from file WHERE filename LIKE 'MAC%';
+-------------------------------------------------+
| filename |
+-------------------------------------------------+
| MAC-1600PVå–扱説明書.pdf |
+-------------------------------------------------+
1 row in set (0.00 sec)
But on my filesystem the file is named:
$ ls files/*MAC*
files/MAC-1600PV取扱説明書.pdf
I have tried to unpack both strings from PHP and the content differ:
The utf-8 sequence read from the filesystem:
=> "MAC-1600PV取扱説明書"
>>> unpack('C*', $u)
...
7 => 48,
8 => 48,
9 => 80,
10 => 86,
11 => 195,
12 => 165,
13 => 226,
14 => 128,
15 => 147,
16 => 195,
17 => 166,
18 => 226,
And for the one read from the database:
...
7 => 48,
8 => 48,
9 => 80,
10 => 86,
11 => 229,
12 => 143,
13 => 150,
14 => 230,
15 => 137,
16 => 177,
So at some-point I lost the original encoding and I have no clue of how to fix my database which is in utf8mb4.
Any advice?

Related

Regex to match multiple one and two digit numbers [duplicate]

This question already has answers here:
Regex matching 5-digit substrings not enclosed with digits
(2 answers)
Retrieve exactly 1 digit using regular expression in python
(3 answers)
Closed 1 year ago.
I'm looking to match numbers that are either 1 or 2 digit (but not more) long so I can add leading zeroes. My input strings look like these:
LL.1 ETX 189
1.20.3.4[8]
1.30.4[17]
229.c.85.8[4]
62.c.80.11
RR 60 H 2
R.60 H 2
Y.11.25[28]
Abc T.14.55
LL 108 ETX 189
Content 1364
With the application of the regex I would hope to identify the following:
LL.1 ETX 189 => match: 1
1.20.300.4[8] => match: 1, 20, 4, 8
1.30.4[17] => match: 1, 30, 4, 17
229.c.85.8[4] => match: 85,8,4
62.c.80.11 => match: 62, 80, 11
RR 60 H 2 => match: 60, 2
R.60 H 2 => match: 60, 2
Y.11.25[28] => match: 11, 25, 28
Abc T.14.55 => match: 14, 55
Whilst ignoring:
LL 108 ETX 189
Content 1364
I thought doing something as simple as: ([1-90-9]{1,2}) would work but this returns the following:
LL.1 ETX 189 => match: 1, 18, 9
1.20.300.4[8] => match: 1, 20, 30, 0, 4, 8
1.30.4[17] => match: 1, 30, 4, 17
229.c.85.8[4] => match: 22, 9, 85,8,4
62.c.80.11 => match: 62, 80, 11
RR 60 H 2 => match: 60, 2
R.60 H 2 => match: 60, 2
Y.11.25[28] => match: 11, 25, 28
Abc T.14.55 => match: 14, 55
LL 108 ETX 189 => match: 10, 8, 18, 9
Content 1364 => match: 13, 64
Any suggestions on how I can achieve this?
I've had a look at this question: 'RegEx Expression /w limited length and chars' and this one: Regex match one digit or two..

How to Create complex Array Structure in PHP

I have to make this kind of structure in array;
We have three ( 3 ) variables which creates this structure:
$numberOfParticipants = 38; // 38 is example
$numberOfParticipantsPerHeat = 8 // 8 is example
$numberOfHeats = 5; // 5 is example
Based on this variables I have this table:
The problem is that, I can't place the ' - ' or null after 31 OR 38. The task is that i have to make the arrays of array "almost equal" like the photo and must depend on the variables above. By the way, after I create the correct list I will slice the array to 5 or 6 or whatever parts I need this is not the problem, the problem is that I have to parse the list like this first. This is what I tried so far:
$calc1 = (int)round($numberOfParticipants * $numberOfParticipantsPerHeat, -1); //First round the numberOfParticipants to closest integer by 10
$readyArr = [];
for ($i = 1; $i <= $calc1; $i++) {
if ($i <= $numberOfParticipants) {
$readyArr[$i] = $i;
} else {
$readyArr[$i] = null;
}
}
The problem with this snippet is that it places the null at the end of the list not after 31, or based on the var.
This is the result I have:
array:40 [▼
1 => 1
2 => 2
3 => 3
4 => 4
5 => 5
6 => 6
7 => 7
8 => 8
9 => 9
10 => 10
11 => 11
12 => 12
13 => 13
14 => 14
15 => 15
16 => 16
17 => 17
18 => 18
19 => 19
20 => 20
21 => 21
22 => 22
23 => 23
24 => 24
25 => 25
26 => 26
27 => 27
28 => 28
29 => 29
30 => 30
31 => 31
32 => 32
33 => 33
34 => 34
35 => 35
36 => 36
37 => 37
38 => 38
39 => null
40 => null
]
The Array after partition I want should be:
array(
0 => array(0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5, 5 => 6, 6 => 7, 7 => 8,),
1 => array(0 => 9, 1 => 10, 2 => 11, 3 => 12, 4 => 13, 5 => 14, 6 => 15, 7 => 16,),
2 => array(0 => 17, 1 => 18, 2 => 19, 3 => 20, 4 => 21, 5 => 22, 6 => 23, 7 => 24,),
3 => array(0 => 25, 1 => 26, 2 => 27, 3 => 28, 4 => 29, 5 => 30, 6 => 31, 7 => null,),
4 => array(0 => 32, 1 => 33, 2 => 34, 3 => 35, 4 => 36, 5 => 37, 6 => 38, 7 => null,),
);
Every help, every clue will be highly appreciated.
There are two things you need to know about the target structure:
How many players are in the first (which will always be the largest, if only by one) set.
$playersPerHeat = ceil($numberOfParticipants / $numberOfHeats);
// note this replaces your hard-coded $numberOfParticipantsPerHeat
You also need to know how many heats actually have that many, that is how many heats are actually full.
$fullHeats = $numberOfParticipants % $numberOfHeats ?: $numberOfHeats;
// The ?: bit means that if we get zero (ie. all equal heats), then we
// count all the heats instead, since they're all full.
Now it's easy!
$players = range(1,$numberOfParticipants);
$heats = array_merge(
array_chunk(
array_slice($players, 0, $fullHeats * $playersPerHeat),
$playersPerHeat
),
array_chunk(
array_slice($players, $fullHeats * $playersPerHeat),
$playersPerHeat - 1
)
);
That's it! Demo

PHP: Most frequent value in array

So I have this JSON Array:
[0] => 238
[1] => 7
[2] => 86
[3] => 79
[4] => 55
[5] => 92
[6] => 55
[7] => 7
[8] => 254
[9] => 9
[10] => 75
[11] => 238
[12] => 89
[13] => 238
I will be having more values in the actual JSON file. But by looking at this I can see that 238 and 55 is being repeated more than any other number. What I want to do is get the top 5 most repeated values in the array and store them in a new PHP array.
$values = array_count_values($array);
arsort($values);
$popular = array_slice(array_keys($values), 0, 5, true);
array_count_values() gets the count of the number of times each item appears in an array
arsort() sorts the array by number of occurrences in reverse order
array_keys() gets the actual value which is the array key in the results from array_count_values()
array_slice() gives us the first five elements of the results
Demo
$array = [1,2,3,4,238, 7, 86, 79, 55, 92, 55, 7, 254, 9, 75, 238, 89, 238];
$values = array_count_values($array);
arsort($values);
$popular = array_slice(array_keys($values), 0, 5, true);
array (
0 => 238,
1 => 55,
2 => 7,
3 => 4,
4 => 3,
)
The key is to use something like array_count_values() to tally up the number of occurrences of each value.
<?php
$array = [238, 7, 86, 79, 55, 92, 55, 7, 254, 9, 75, 238, 89, 238];
// Get array of (value => count) pairs, sorted by descending count
$counts = array_count_values($array);
arsort($counts);
// array(238 => 3, 55 => 2, 7 => 2, 75 => 1, 89 => 1, 9 => 1, ...)
// An array with the first (top) 5 counts
$top_with_count = array_slice($counts, 0, 5, true);
// array(238 => 3, 55 => 2, 7 => 2, 75 => 1, 89 => 1)
// An array with just the values
$top = array_keys($top_with_count);
// array(238, 55, 7, 75, 89)
?>

Create a multidimensional array from mysql data

I was wondering how I get a multidimensional array that looks like this:
array(
"wifi" => array(
16 => 499,
32 => 599,
64 => 699
),
"wifi+3G" => array(
16 => 629,
32 => 729,
64 => 829)
);
Out of a mysql table that looks like this:
id, model, grootte, prijs
1, Wifi, 16, 449
2, Wifi, 32, 549
3, Wifi+3G, 16, 499
4, Wifi+3G, 32, 599
Just use one or more fields from your DB results as the keys in the array:
$arr = array();
while($row = mysql_fetch_assoc($result)) {
$arr[$row['somekey']][$row['otherkey']] = $row;
}

Calculate overall and division ranking via arrays

This is a follow-up to Detect future duplicate values while iterating through MySQL results in PHP.
I have an SQL query which produces the results:
team_id division_id wins
-------------------------------
10 2 44
9 2 42
5 1 42
2 1 42
3 1 41
11 2 40
1 1 36
8 2 31
7 2 29
12 2 24
4 1 20
6 1 18
I'm trying to calculate a given team's overall and divisional rankings.
For example, team_id = 1:
Overall: 7
Divisional: 4
For team_id = 3:
Overall: 5
Divisional: 3
For team_id = 9:
Overall: T-2 //must indicate tie
Divisional: 2
As you can see from the linked previous question/answer, I can calculate the Overall rank just fine. The issue comes with calculating the divisional rank as well (including properly handling ties).
I've tried storing the results in a multi-dimensional array like $arr['wins']['division_id']['team_id'], such as...
44 => 2 => 10
42 => 1 => 5
2
2 => 9
41 => 1 => 3
40 => 11 => 2
...
But am stuck as to how to iterate through and get my two respective ranks, as well as detecting ties appropriately for each.
Try something like this:
// Dataset as defined on question
$arr = array(
array('team_id' => 10, 'division_id' => 2, 'wins' => 44),
array('team_id' => 9, 'division_id' => 2, 'wins' => 42),
array('team_id' => 5, 'division_id' => 1, 'wins' => 42),
array('team_id' => 2, 'division_id' => 1, 'wins' => 42),
array('team_id' => 3, 'division_id' => 1, 'wins' => 41),
array('team_id' => 11, 'division_id' => 2, 'wins' => 40),
array('team_id' => 1, 'division_id' => 1, 'wins' => 36),
array('team_id' => 8, 'division_id' => 2, 'wins' => 31),
array('team_id' => 7, 'division_id' => 2, 'wins' => 29),
array('team_id' => 12, 'division_id' => 2, 'wins' => 24),
array('team_id' => 4, 'division_id' => 1, 'wins' => 20),
array('team_id' => 6, 'division_id' => 1, 'wins' => 18));
$divisionTeam = array();
$divisionWins = array();
foreach($arr as $team) {
$divisionTeam[$team['division_id']][] = $team['team_id'];
$divisionWins[$team['division_id']][] = $team['wins'];
}
echo "<pre>";
foreach (array_keys($divisionTeam) as $division_id) {
$rank = 0;
$prevWins = -1;
echo "DIVISION $division_id \n";
foreach ($divisionTeam[$division_id] as $index => $team_id) {
if ($prevWins == $divisionWins[$division_id][$index]) {
echo $team_id . " T - " . $rank . "\n";
}
else {
$rank++;
echo $team_id . " " . $rank . "\n";
}
$prevWins = $divisionWins[$division_id][$index];
}
}
echo "</pre>";

Categories