I have created some data using Cassandra DB 2.0.1 (CQL 3)
CREATE TABLE fans (id text PRIMARY KEY, fans map<text, text>);
INSERT INTO fans (id, fans) VALUES ('John', {'fruit' : 'apple', 'band' : 'Beatles'});
UPDATE fans SET fans = fans + {'movie' : 'Cassablanca'} WHERE id = 'John';
It work's fine.
cqlsh:testdb> SELECT * FROM fans;
id | fans
------+---------------------------------------------------------------
John | {'band': 'Beatles', 'fruit': 'apple', 'movie': 'Cassablanca'}
(1 rows)
Now I'm trying to get data with PHP (thobbs/phpcassa v1.1.0).
include_once ("/include/autoload.php");
$pool = new phpcassa\Connection\ConnectionPool('testdb');
$connection = $pool->get();
$rows = $connection->client->execute_cql3_query("SELECT id, fans FROM fans", cassandra\Compression::NONE, cassandra\ConsistencyLevel::ONE);
var_dump($rows->rows);
$pool->return_connection($connection);
unset($connection);
$pool->close();
It also work's fine.
array (size=1)
0 =>
object(cassandra\CqlRow)[10]
public 'key' => string '' (length=0)
public 'columns' =>
array (size=2)
0 =>
object(cassandra\Column)[11]
public 'name' => string 'id' (length=2)
public 'value' => string 'John' (length=4)
public 'timestamp' => null
public 'ttl' => null
1 =>
object(cassandra\Column)[12]
public 'name' => string 'fans' (length=4)
public 'value' => string '��band�Beatles�fruit�apple�movie�Cassablanca' (length=51)
public 'timestamp' => null
public 'ttl' => null
The problem is how to unpack the value that represented as a map?
I can see
��band�Beatles�fruit�apple�movie�Cassablanca
and I know it showld be
{'band': 'Beatles', 'fruit': 'apple', 'movie': 'Cassablanca'}
Is there any internal function to deserialize or unpack that encoded string into a map or array?
I wroute a function that reads non-printable symbols:
function unistr_to_ords($str, $encoding = 'UTF-8') {
$str = mb_convert_encoding($str, 'UCS-4BE', $encoding);
$ords = array();
for ($i = 0; $i < mb_strlen($str, 'UCS-4BE'); $i++) {
$s2 = mb_substr($str, $i, 1, 'UCS-4BE');
$val = unpack('N', $s2);
$ords[] = $val[1];
}
return($ords);
}
And when I try it with that value I see the following result:
array (size=51)
0 => int 0
1 => int 3
2 => int 0
3 => int 4
4 => int 98
5 => int 97
6 => int 110
7 => int 100
8 => int 0
9 => int 7
10 => int 66
11 => int 101
12 => int 97
13 => int 116
14 => int 108
15 => int 101
16 => int 115
17 => int 0
18 => int 5
19 => int 102
20 => int 114
21 => int 117
22 => int 105
23 => int 116
24 => int 0
25 => int 5
26 => int 97
27 => int 112
28 => int 112
29 => int 108
30 => int 101
31 => int 0
32 => int 5
33 => int 109
34 => int 111
35 => int 118
36 => int 105
37 => int 101
38 => int 0
39 => int 11
40 => int 67
41 => int 97
42 => int 115
43 => int 115
44 => int 97
45 => int 98
46 => int 108
47 => int 97
48 => int 110
49 => int 99
50 => int 97
As I understood 0 (zero) is a splitter, after 0 is a length, e.g. first 03 means 3 items in the map. Then 04 means 4 is a length of word 'band', then 07 means new word with length 7 for word 'Beatles' on so on.
But is any internal built-in method or function to extract map, list or set?
Somebody may have hacked something together, but for now the official answer is that phpcassa doesn't support CQL3 and hence doesn't support CQL3-only features like column collections (maps, sets, and lists).
I was hoping to just find something to do this, but couldn't so I hacked this up. Works for a map of <text,text>. Which is what I'm using. Thought I'd put it on here for anyone else looking.
function cql3_map_to_array($map) {
$byte_array = unpack('C*', $map);
$map_array = array();
if(sizeof($byte_array) > 2) {
$pos = 1;
$size = (intval($byte_array[$pos]) * 256) + intval($byte_array[$pos + 1]);
$pos += 2;
while($size > 0) {
$length = (intval($byte_array[$pos]) * 256) + intval($byte_array[$pos + 1]);
$pos += 2;
$key = substr($map, $pos - 1, $length);
$pos += $length;
$length = (intval($byte_array[$pos]) * 256) + intval($byte_array[$pos + 1]);
$pos += 2;
$value = substr($map, $pos - 1, $length);
$pos += $length;
$map_array[$key] = $value;
$size--;
}
}
return $map_array;
}
Related
I have a site with a search feature but am trying to improve the search for a fuzzy search.
So far what I've done is query all of my products and use similar_text() to see how close they are to the actual search term
I then create an array where the key is how similar it is and the value is the product id. I then sort this by the key/similarity.
$term = $_GET['search_term'];
$similar_array = [];
$sql = "SELECT * FROM products";
$stmt = DB::run($sql);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$id = $row["pro_id"];
$result = $row['product'];
similar_text($term,$result,$similarity);
$similar_array[$similarity][] = $id;
}
$closest_match = array_keys($similar_array);
rsort($closest_match);
$match_count = count($closest_match);
for($i=0; $i<$match_count; $i++){
var_dump($similar_array[$closest_match[$i]]);
}
This gives me something like:
array (size=9)
0 => int 28
1 => int 1628
2 => int 1665
3 => int 1666
4 => int 1667
5 => int 1668
6 => int 1669
7 => int 1670
8 => int 1671
C:\wamp64\www\V2\search.php:65:
array (size=2)
0 => int 37
1 => int 38
C:\wamp64\www\V2\search.php:65:
array (size=1)
0 => int 481
C:\wamp64\www\V2\search.php:65:
array (size=3)
0 => int 27
1 => int 1009
2 => int 1620
C:\wamp64\www\V2\search.php:65:
array (size=14)
0 => int 30
1 => int 104
2 => int 131
3 => int 134
4 => int 168
5 => int 169
6 => int 170
7 => int 557
8 => int 1011
9 => int 1014
10 => int 1661
11 => int 1662
12 => int 1663
13 => int 1664
I have a show_products() function that I just need to pass an array of ID's, so what I want to do now is take the multiple arrays of ID's from above and merge it in this specific order and then crop the array to a certain number so it won't have every product but will cut off after so many results.
As per your query you can use follow below steps
you merge all array by array_merge
sort the array using rsort (highest merge come first);
for display you can use array_slice or array_chunk
I have an array like this:
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
is there a way to output a new array of 10 ranges with key that tells me which is used and frequency as values?
$result = array(
[x0] => frequency // number of values <= x0
[x1] => frequency // number of values > x0 and <=1
etc..., [x2], ...., [x7], x[8]
[x9] => frequency // number of values >= x9
)
use this for 10 equal segments
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$step = (max($array) - min($array)) / 10;
$result = [];
for ($i = min($array); $i < max($array) - $step; $i += $step) {
$res = array_filter($array, function($v) use ($i, $step) {
return ($i <= $v) && $v < $i +$step;
});
$result[$i . '-' . ($i + $step)] = $res;
}
Return:
"10 - 14.8" => 2
"14.8 - 19.6" => 2
"19.6 - 24.4" => 0
"24.4 - 29.2" => 5
"29.2 - 34" => 0
"34 - 38.8" => 2
"38.8 - 43.6" => 0
"43.6 - 48.4" => 3
"48.4 - 53.2" => 0
"53.2 - 58" => 0
You can use array_count_values() to count values
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$vals = array_count_values($array);
echo "<pre>"; print_r($vals);
This will give you
Array
(
[10] => 1
[25] => 3
[47] => 1
[14] => 1
[45] => 2
[58] => 1
[29] => 1
[15] => 2
[36] => 1
[27] => 1
[34] => 1
)
I've used an array for the range boundaries. Here with an example of 4 irregular ranges. And dumped the sorted array to make it easier to see if the results are as you'd expect.
<?php
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$bounds = array(0,10,25,50,100);
$lower = array_shift($bounds);
$range_frequencies = array();
sort($array);
var_dump($array);
foreach($bounds as $upper) {
$range_frequencies[$lower . '-' . $upper] = 0;
foreach($array as $k => $v) {
if($v > $lower && $v <= $upper) {
$range_frequencies[$lower . '-' . $upper]++;
unset($array[$k]);
}
}
$lower = $upper;
}
var_dump($range_frequencies);
Output:
array (size=15)
0 => int 10
1 => int 14
2 => int 15
3 => int 15
4 => int 25
5 => int 25
6 => int 25
7 => int 27
8 => int 29
9 => int 34
10 => int 36
11 => int 45
12 => int 45
13 => int 47
14 => int 58
array (size=4)
'0-10' => int 1
'10-25' => int 6
'25-50' => int 7
'50-100' => int 1
Based on Manjeet Barnala's answer:
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$vals = array_count_values($array);
arsort($vals);
$vals = array_slice($vals,0,10,true);
var_dump($vals);
I have an array like this one:
array (size=1)
0 =>
array (size=33)
0 => int 126
1 => int 43
2 => int 4
3 => int 0
4 => int 3
5 => int 3
6 => int 30
7 => int 15
8 => int 22
9 => int 27
10 => int 22
11 => int 46
12 => int 0
13 => int 8
14 => int 14
15 => int 8
array (size=1)
1 =>
array (size=33)
0 => int 273
1 => int 3
2 => int 4
3 => int 28
4 => int 36
5 => int 19
6 => int 142
7 => int 81
8 => int 59
9 => int 71
10 => int 88
11 => int 47
12 => int 42
13 => int 0
14 => int 12
15 => int 97
(of course it is way longer)
and I need both to sum all the value with the same key and count how many values with the same key are >0 (cause I have to find the avarage of all the numbers >0
My expected result is
0=>
'sum' => 399
'count'=>2
1=>
'sum' =>46
'count'=>2
how can I create this array?
There's an inbuilt function in PHP to count the sum of all the elements of an array. Here, this will give you your expected output :
<?php
$arr = [[10, 20, 30, 40], [10, 20, 30], [10, 20, 30, 4]];
// Let the magic happen...
$yourArray = array_map(function ($el){ return ["sum" => array_sum($el), "count" => count($el)]; }, $arr);
print_r($yourArray);
?>
I have thought about this, and came up with a solution (I think...), it comes in the form of a function and it goes like this:
function getSumAndCount(array $arr)
{
$sum = 0;
$count = 0;
foreach ($arr as $v)
{
$count++;
if (is_array($v))
{
$next = getSumAndCount($v);
$count += $next['count'];
$sum += $next['sum'];
}
else
{
!is_numeric($v) ?: $sum += $v;
}
}
return [ 'sum' => $sum, 'count' => $count ];
}
It has a recursive check to if the array is multidimensional, checks if the value is numeric and sets the count and sum in a return array.
I haven't tested this properly as yet, but please test and let me know if you get the desired output.
EDIT
I will extend this to count dupe keys soon
I'm working on it
$source = mb_convert_encoding('test', "unicode", "utf-8");
$source = unpack('C*', $source);
var_dump($source);
return:
array (size=8)
1 => int 0
2 => int 116
3 => int 0
4 => int 101
5 => int 0
6 => int 115
7 => int 0
8 => int 116
but i want this return:
array (size=8)
1 => int 116
2 => int 0
3 => int 101
4 => int 0
5 => int 115
6 => int 0
7 => int 116
8 => int 0
I want use this return in openssl function for encryption. just $source important to me, i write other code for debugging.
What can i do to solve this problem?
"Unicode" is not a real encoding; it's the name of the overarching standard and used as an alias for UTF-16BE mostly by Microsoft, and apparently PHP supports it for that reason. What you expect is UTF-16LE, so use that explicitly:
$source = mb_convert_encoding('test', 'UTF-16LE', 'UTF-8');
I can't figure out why asort isn't working. Neither does any other sort work. $hs['hs_type'] are values that come from MySQL query.
$results = $query->result_array();
$hs_types = array();
foreach($results as $hs) {
$hs_types[$hs['hs_type']]++;
}
$projects = array();
foreach($hs_types as $hs) {
array_push($projects, $hs);
}
asort($projects);
var_dump for my array before sort: array (size=15)
* 8 => int 1709
* 13 => int 26
* 7 => int 474
* 14 => int 800
* 11 => int 282
* 6 => int 61
* 5 => int 23
* 15 => int 181
* 3 => int 2
* 19 => int 3
* 9 => int 50
* 1 => int 44
* 2 => int 2
* 4 => int 4
* 18 => int 13
var_dump for my array after sort: array (size=15)
* 8 => int 2
* 12 => int 2
* 9 => int 3
* 13 => int 4
* 14 => int 13
* 6 => int 23
* 1 => int 26
* 11 => int 44
* 10 => int 50
* 5 => int 61
* 7 => int 181
* 4 => int 282
* 2 => int 474
* 3 => int 800
* 0 => int 1709
What I wanted:
* 3 => int 2
* 2 => int 2
* 19 => int 3
* 4 => int 4
* 18 => int 13
* 5 => int 23
* 13 => int 26
* 1 => int 44
* 9 => int 50
* 15 => int 181
* 11 => int 282
* 7 => int 474
* 14 => int 800
* 8 => int 1709
Problem is that you are getting everything into your nicely keyed array, then pushing each item into the $projects array (losing the key) then doing a asort on the $projects array.
It shows up with this minor test script:-
<?php
$hs_types = array(8 => 1709,
13 => 26,
7 => 474,
14 => 800,
11 => 282,
6 => 61,
5 => 23,
15 => 181,
3 => 2,
19 => 3,
9 => 50,
1 => 44,
2 => 2,
4 => 4,
18 => 13);
Echo "\r\nOriginal array\r\n";
print_r($hs_types);
$projects = array();
foreach($hs_types as $hs)
{
array_push($projects, $hs);
}
asort($projects);
Echo "\r\nPushed array sorted\r\n";
print_r($projects);
asort($hs_types);
Echo "\r\nOriginal array sorted\r\n";
print_r($hs_types);
?>
but it looks like it would be easier to just get the sorted list in SQL in the first place.
I tried using your array with asort() and it worked perfectly, coming back with the result you expected:
<?php
//your array
$a = array(
8 => 1709,
13 => 26,
7 => 474,
14 => 800,
11 => 282,
6 => 61,
5 => 23,
15 => 181,
3 => 2,
19 => 3,
9 => 50,
1 => 44,
2 => 2,
4 => 4,
18 => 13
);
//print unsorted array
print_r($a);
//sort the array
asort($a);
//print the sorted array
echo "<br/><br/>";
print_r($a);
If this really isn't working for you, why not do the sorting in the SQL query instead? Then you wouldn't need to bother re-sorting it in PHP.
Are you sure you are using asort instead of sort ? I tried your code and it works perfectly :
<?php
$myArray = array(
8 => 1709,
13 => 26,
7 => 474,
14 => 800,
11 => 282,
6 => 61,
5 => 23,
15 => 181,
3 => 2,
19 => 3,
9 => 50,
1 => 44,
2 => 2,
4 => 4,
18 => 13,
);
var_dump($myArray);
asort($myArray);
var_dump($myArray);
?>
My result :