I have a query like this:
$content = "How technology is helping to change the way people think about the food on their plate and the food impact for them. Technology could have a role to play in raising awareness of the impact our diets have on the planet.";
$exp = explode(" ", $content)
for($j = 0; $j < count($exp); $j++){
$this->db->query("INSERT INTO news (news_id, news_content) VALUES ('$id', $exp[$j])");
}
But, I don't want to insert all the words, i just need to insert the word that only appear more than once (technology, food, impact). Is it possible to do that? can someone help me?
I would process the text content using array_filter to exclude words that are in a stopword list, then count the occurrences of each word using array_count_values and then array_filter out the words that occur only once. You can then write the remaining words (which will be the keys of the output array) to the database. For example:
$content = "How technology is helping to change the way people think about the food on their plate and the food impact for them. Technology could have a role to play in raising awareness of the impact our diets have on the planet.";
$stopwords = array('how', 'is', 'to', 'the', 'way', 'on', 'and', 'for', 'a', 'in', 'of', 'our', 'have');
// count all words in $content not in the stopwords list
$counts = array_count_values(array_filter(explode(' ', strtolower($content)), function ($w) use ($stopwords) {
return !in_array($w, $stopwords);
}));
// filter out words only seen once
$counts = array_filter($counts, function ($v) { return $v > 1; });
// write those words to the database
foreach ($counts as $key => $value) {
$this->db->query("INSERT INTO news (news_id, news_content) VALUES ('$id', '$key')");
}
For your sample data, the final result in $counts will be:
Array
(
[technology] => 2
[food] => 2
[impact] => 2
)
There are a lot of options here I believe.
Here is my solution(s): You could use search_array() for this. The search array returns false if no other needle is found in_array in an array. If another word is found it returns the key.
Depending of your needs, you could use one of these options below.
//Option 1
//Words that actually appear more than once...
$new_arr = array();
foreach($exp as $key=>$e) {
//Must be this word only (therefore the true-statement
$search = array_search($e, $exp, true);
if ($search !== false && $search != $key) {
$new_arr[] = $e;
}
}
//Option 2
//
//Your question was not totally clear so I add this code as well
//Words with asterixes before and after that appear more than once
$new_arr = array();
foreach($exp as $key=>$e) {
//Two asterixes at the beginning of the sting and two at the end
//strtolower sets **Technology** and **technology** as a duplicate of word
if (substr($e,0,2) == "**" && substr($e,-2,2) == "**") {
$search = array_search(strtolower($e), $exp);
if ($search !== false && $search != $key) {
$new_arr[] = $e;
}
}
}
for($j = 0; $j < count($new_arr); $j++){
$this->db->query("INSERT INTO news (news_id, news_content)
VALUES ('$id', $new_arr[$j])");
}
As someone mentioned in a comment you should prevent SQL injections by typing that way in the INSERT-statement (and you should), but the question was mainly about finding duplicates in a string in do something with them so therefore I won't go further with that comment.
The result array $new_arr would like: (option 1)
array (size=9)
0 => string 'the' (length=3)
1 => string 'the' (length=3)
2 => string '**food**' (length=8)
3 => string 'to' (length=2)
4 => string 'the' (length=3)
5 => string '**impact**' (length=10)
6 => string 'have' (length=4)
7 => string 'on' (length=2)
8 => string 'the' (length=3)
The reason why Technology and technology is not the same because that its an uppercase T in one of the words.
The result array $new_arr would like: (option 2)
array (size=3)
0 => string '**food**' (length=8)
1 => string '**Technology**' (length=14)
2 => string '**impact**' (length=10)
Related
I have a string:
01;Tommy;32;Coder&&02;Annie;20;Seller
I want it like this:
array (size=2)
0 =>
array (size=4)
0 => string '01' (length=2)
1 => string 'Tommy' (length=5)
2 => int 42
3 => string 'Coder' (length=5)
1 =>
array (size=4)
0 => string '02' (length=2)
1 => string 'Annie' (length=5)
2 => int 20
3 => string 'Seller' (length=6)
Hope you can help me, thank you!
Not sure if the datatypes will be matching (as I believe it's all in a string) but here's the code
$myarray = array();
foreach(explode("&&",$mystring) as $key=>$val)
{
$myarray[] = explode(";",$val);
}
The explode command takes a string and turns it into an array based on a certain 'split key' which is && in your case
but since this is a dual array, I had to pass it through a foreach and another explode to solve.
It's very simple. First you need to explode the string by && and then traverse through array exploded by &&. And explode each element of an array by ;.
Like this,
<?php
$str="01;Tommy;32;Coder&&02;Annie;20;Seller";
$array=explode("&&",$str);
foreach($array as $key=>$val){
$array[$key]=explode(";",$val);
}
print_r($array);
Demo: https://eval.in/629507
you should just have to split on '&&', then split the results by ';' to create your new two dimensional array:
// $string = '01;Tommy;32;Coder&&02;Annie;20;Seller';
// declare output
$output = [];
// create array of item strings
$itemarray = explode('&&',$string);
// loop through item strings
foreach($itemarray as $itemstring) {
// create array of item values
$subarray = explode(';',$itemstring);
// cast age to int
$subarray[2] = (int) $subarray[2]; // only useful for validation
// push subarray onto output array
$output[] = $subarray;
}
// $output = [['01','Tommy',32,'Coder'],['02','Annie',20,'Seller']];
keep in mind that since php variables are not typed, casting of strings to ints or keeping ints as strings will only last depending on how the values are used, however variable type casting can help validate data and keep the wrong kind of values out of your objects.
good luck!
There is another appropach of solving this problem. Here I used array_map() with anonymous function:
$string = '01;Tommy;32;Coder&&02;Annie;20;Seller';
$result = array_map(function($value){return explode(';',$value);}, explode('&&', $string));
I am trying to produce a HTML list grouped by "groupName" from the array below.
array (size=30)
0 =>
array (size=4)
'groupOrder' => string '1' (length=1)
'groupName' => string 'Class' (length=11)
'txt' => string '............' (length=32)
'ID' => string '6' (length=1)
1 =>
array (size=4)
'groupOrder' => string '1' (length=1)
'groupName' => string 'Size' (length=11)
'txt' => string '..................' (length=34)
'ID' => string '6' (length=1)
2 =>
...
So I'd like produce something like this pseudo list:
groupName
txt
txt
txt
next GroupName
txt
txt
...
So my code looks like this
foreach ($datafeed as $val => $row) {
if (($datafeed[$val]['groupName']) == next($datafeed[$val]['groupName'])) {
//same group - do nothing
} else {
echo $datafeed[$val]['groupName'];
}
echo "<li>".$row['txt']. "</li>";
}
But I'm getting errors about "next() expects parameter 1 to be array, string given".
I've tried all sorts of different syntax, but I'm not making much progress. How do I compare two values in a nested array?
You misinterpreted the meaning of the function next(): you cannot query it for an array element. It manipulates the internal array pointer tied with the array itself, not with some its element. From the PHP documentation:
Every array has an internal pointer to its "current" element, which is initialized to the first element inserted into the array.
and see also a description of next.
Since the foreach loop crucially depends on the value of the array pointer, messing with the array pointer will ruin the loop: you probably see every second element in the loop, because at every iteration once next() is called by your foreach loop and then once by yourself.
The simplest thing for you is probably to use the old good for loop:
for ($i = 0; $i < length ($array); $i++)
{
if ($i == 0 || $array[$i] != $array[$i - 1])
echo "New group!\n";
echo $array[$i];
}
This doesn't answer your question directly, but you'd be better off restructuring your array so that they're grouped, and you don't need to perform any logic within the loop to check the groupName. Currently, you're relying on the next groupName to match the current groupName, but if they're not sequential, they won't be grouped.
You could do something like this:
$output = array();
foreach ($datafeed as $feed) {
$output[$feed['groupName']][] = $feed;
}
Here's a demo
You should not use next inside a foreach loop anyway, since you'll get conflicting array pointer movements. Simply store the last value:
$last = null;
foreach (...) {
if ($last != $row['current']) {
// new group
}
$last = $row['current'];
...
}
I am having the following array defined:
array(
'name'=>'Blue',
'age'=>'0',
'skin'=>array(
'White Skin','Tanned Skin'
),
'eye'=>array(
'Black','Brown','Honey'
),
'personality'=>array(
'Intelligent','Warm','Trustworthy','Sweet'
),
'ocassion'=>array(
'Every day wear','Celebrations','Restaurant Dinner','Feasts','Visiting friends'
),
'hair'=>'All Colors',
'style'=>array(
'Loved to be admired','Center of attention'
),
'description'=>'Blue lens are perfect for any..'
);
and I am trying to find the number of matches, from an HTML form into this array. A possible return from the HTML form, in array format would be:
Array
(
[age] => 16
[skin] => Tanned Skin
[eye] => Brown
[personality] => Array
(
[0] => Intelligent
[1] => Warm
[2] => Trustworthy
)
[ocassion] => Weddings
[hair] => Dark Brown
[style] => Array
(
[0] => Style Queen
[1] => Testing val
)
)
I have tried iterating trough each key of the first array, but failed to achieve what I want, and also I've tried using the function array_intersect_assoc($stack,$search) but it seems it won't find the exact matches because the $search array ( second example ) has some key=>value pairs that are of type string, and it cannot match any occurrence into the first array because the value is actually an array, and not a string.
Can someone point me an idea or can let me know what's best to do over here?
I have tried a lot of things in the last 3 hours but no success.
Ok, so how about this.
The source data:
$demands = array(
'name'=>'Blue',
'age'=>'0',
'skin'=>array(
'White Skin','Tanned Skin'
),
'eye'=>array(
'Black','Brown','Honey'
),
'personality'=>array(
'Intelligent','Warm','Trustworthy','Sweet'
),
'ocassion'=>array(
'Every day wear','Celebrations','Restaurant Dinner','Feasts','Visiting friends'
),
'hair'=>'All Colors',
'style'=>array(
'Loved to be admired','Center of attention'
),
'description'=>'Blue lens are perfect for any..'
);
$possible_match = array(
'age'=>'16',
'skin'=>'Tanned Skin',
'eye'=>'Brown',
'personality'=>array(
'Intelligent','Warm','Trustworthy'
),
'ocassion'=>array(
'Weddings'
),
'hair'=>'Dark Brown',
'style'=>array(
'Style Queen','Testing value'
)
);
And the match-making algorithm:
$result = array();
$count_matches = 0;
// Go through all the demands
foreach ($demands as $key => $value){
// If there's a matching key in the possible match array
if (isset($possible_match[$key])){
// If there are more demanded values
if (is_array($value)){
// Let all demanded values be lowercase
$value = array_map('strtolower', $value);
// If there are more possible matching values
if (is_array($possible_match[$key])){
// Let all possibly matching values be lowercase, too
$possible_match[$key] = array_map('strtolower', $possible_match[$key]);
// And then do the intersect.
$intersect = array_intersect($value, $possible_match[$key]);
if ($intersect){
// If that intersect is not empty, add that to the resulting array
$result[$key] = $intersect;
$count_matches += count($intersect);
};
} else {
// If there's only one possible matching value, search that
// value in the demaned array
if (in_array(strtolower($possible_match[$key]), $value, true)){
// And add it to the results
$result[$key][] = strtolower($possible_match[$key]);
$count_matches++;
}
}
} else {
if (is_array($possible_match[$key])){
// If there are more possible matching values but the demand is a string,
// find that string in those possible values
$possible_match[$key] = array_map('strtolower', $possible_match[$key]);
if (in_array(strtolower($value), $possible_match[$key], true)){
// And add it to the results
$result[$key] = $value;
$count_matches++;
}
} else {
// If the demanded value is only one (= it's a string and not an array)
// and the possible match is also a string, do a lowercase compare
// + if there's a word "all" in the demanded value, pass it at all times ;D
if (strtolower($possible_match[$key]) == strtolower($value)
|| stripos($value, "all") !== false){
// And add it to the resulting array
$result[$key] = strtolower($value);
$count_matches++;
}
}
}
}
}
var_dump ($result);
var_dump ($count_matches);
There may be some opportunities for optimizing, but the basic idea should be there :)
The result:
array (size=4)
'skin' =>
array (size=1)
0 => string 'tanned skin' (length=11)
'eye' =>
array (size=1)
0 => string 'brown' (length=5)
'personality' =>
array (size=3)
0 => string 'intelligent' (length=11)
1 => string 'warm' (length=4)
2 => string 'trustworthy' (length=11)
'hair' => string 'all colors' (length=10)
Plus the count, if you'd like:
int 6
I am trying to figure out how to get values out of a checkbox array. The checkbox array var_dump looks like the following:
array (size=50)
0 => string '104702|0' (length=8)
1 => string '52278|1' (length=7)
2 => string '69891|1' (length=7)
3 => string '153335|1' (length=8)
4 => string '131140|1' (length=8)
. . .
I am sending two different IDs in each array value, separated by a pipe and would like to assign each part to different variables, $variable1, $variable2, so I can use them in a database query. How can I do this?
Thanks for your help.
EDIT: Even though I've accepted an answer below, here is the complete answer I was looking for:
To get the values out of the above array so I can use them in my database query, I did the following to first break them apart:
foreach ($input as $key => $value) {
$this->combinedIds[] = explode('|', $value);
}
Then, to get the values into separate variables, I did the following:
foreach ($this->combinedIds as $key => $value) {
$firstId = $value[0];
$secondId = $value[1]
// do something with the values ...
}
Use foreach loop on the array and explode each value with pipe symbol. Something like this :
foreach ($arr as $val)
{
$newData = explode("|", $val);
}
A different variant (using an anonymous function) would be something like:
$values = array_map(function ($input) { $tmp = explode("|", $input); return ["id1" => current($tmp), "id2" => end($tmp)]; }, $array);.
This is written for PHP 5.4+. If you need a version compatible with PHP 5.3 and downwards, just substitute the brackets with its corresponding array(...) equivalent.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Algorithm: Extract subset based on property sum
in the simple case we have an array:
{6, 1, 3, 11, 2, 5,12}
and we want to know all combinations the sum of elements contained in that array to getting 12.
in this case we will get four combinations:
12
1 + 11
6 + 5 + 1
1 + 3 + 2 + 6
so, how can we do this in BASIC or PHP?. maybe pseudo-code first ;-).
I've been looking but there just got a combination with a predetermined number of elements.
You can try
echo "<pre>";
$sum = 12 ; //SUM
$array = array(6,1,3,11,2,5,12);
$list = array();
# Extract All Unique Conbinations
extractList($array, $list);
#Filter By SUM = $sum
$list = array_filter($list,function($var) use ($sum) { return(array_sum($var) == $sum);});
#Return Output
var_dump($list);
Output
array
0 =>
array
1 => string '1' (length=1)
2 => string '2' (length=1)
3 => string '3' (length=1)
4 => string '6' (length=1)
1 =>
array
1 => string '1' (length=1)
2 => string '5' (length=1)
3 => string '6' (length=1)
2 =>
array
1 => string '1' (length=1)
2 => string '11' (length=2)
3 =>
array
1 => string '12' (length=2)
Functions Used
function extractList($array, &$list, $temp = array()) {
if (count($temp) > 0 && ! in_array($temp, $list))
$list[] = $temp;
for($i = 0; $i < sizeof($array); $i ++) {
$copy = $array;
$elem = array_splice($copy, $i, 1);
if (sizeof($copy) > 0) {
$add = array_merge($temp, array($elem[0]));
sort($add);
extractList($copy, $list, $add);
} else {
$add = array_merge($temp, array($elem[0]));
sort($add);
if (! in_array($temp, $list)) {
$list[] = $add;
}
}
}
}
The problem is NP-Hard. Even determining if there is ANY subset of the problem that sums to the desired number is NP-Hard (known as the subset sum problem), and there is no known polynomial solution to it.
Thus, you should look for an exponantial solution, such as a backtracking one - generate all possible combinations, and check if they are valid.
You can use trimming to get your search faster (for example, if you generate a partial subset of sum 13, no need to check other subsets which are supersets of this subset, since they will definetly won't lead to a solution.
pseudo code:
findValidSubsets(sum,arr,idx,currSolution):
if (sum == 0):
print currSolution
if (sum < 0): //trim the search, it won't be succesful
return
//one possibility: don't take the current candidate
findPermutations(sum,arr,idx+1,currSolution)
//second poassibility: take the current candidate
currSolution.add(arr[idx])
findPermutations(sum-arr[idx],arr,idx+1,currSolution)
//clean up before returning:
currSolution.removeLast()
Complexity is O(2^n) - need to generate at worst case all 2^n possible subsets
Invoke with findValidSubsets(desiredSum,myArray,0,[]), where [] is an empty initial list
using dynamic programming you can express solution as
solver(sum,start_index)
stop_condition_here_when sum <= 0
r=0
for i=start_index ; i < last_iddex :
r += solver(sum - array[i],i+1)
r += solver(sum ,i+1)
return r
And adding extra memositaion would also speedup this program
You can iterate over the length of the set. In each step, check all subsets of length k:
for k = 1 to size(input):
foreach permutation p of length k:
if sum(p) == 12:
bam!