Transforming array with numbers and operators - javascript

I manage to have this arraylist :
["1","2","+","2","1","2"]
But I would like to sort it in order to have
["12","+","212"]
But I can't figure out how to this.
UPDATE :
let al = ["1","2","+","2","1","2"];
for(let i=0;i.length;i++) {
if(al[i] != "+" && al[i+1]) {
al[i] += al[i+1];
}
}
I think I could use a while loop

Combine join and split by regex:
var a = ["1","2","+","2","1","2"];
a = a.join('').split(/([x^+-])/);
console.log(a);

You could join and split by word boundary position, without mention the operators.
var array = ["1", "2", "+", "2", "1", "2"],
result = array.join('').split(/\b/);
console.log(result);

This is the easiest way. Just write a reducer to append tokens to a stack.
const OPERATORS = /[+\-\*\/]/;
function toExpression(tokens) {
return tokens.reduce((result, token) => {
if (OPERATORS.test(token)) {
result.push(token, '');
} else {
result[result.length - 1] += token;
}
return result;
}, ['']);
}
let arr1 = ["1", "2", "+", "2", "1", "2"];
let arr2 = toExpression(arr1);
console.log(JSON.stringify(arr2));
.as-console-wrapper { top: 0; max-height: 100% !important; }

Just go over the array and join everytging except the + :
const array = ["1", "2", "+", "2", "1", "2"]
const result = [];
let curr = "";
for (const el of array) {
if (el == "+") {
result.push(curr, el);
curr = "";
} else {
curr += el;
}
}
result.push(curr);
console.log(result)

Related

i couldn't figure out how can i make the object dynamically

as you can see i get the "p" array from a html form, and i want to make a dynamic object from the "p" array here
function filter(p){
var obj;
console.log(p);//[ 'Grade', '>','123']
if(p[1]== ">"){p[1]=gt}
obj = {
$and:[
{p[0]: {$p[1]: p[3}}
]
}
return obj;
}
to pass it to this aggregation function:
async function query(DS,filter,q1,q2,q3){
arr.length = 0;
var obj;
var x = [];
var y = [];
var filtered;
const projection = { _id: 0 }; projection[q1] = 1; projection[q2] = 1;
const grouping ={}; grouping[q1]=q1; grouping[q2] = q2;
filtered = await DS.aggregate([
{$project: projection},
{$match: filter}
]).toArray()
}
if(q3 == ""){
for (let i = 0; i < filtered.length; i++) {
obj = filtered[i]
x.push(obj[q1])
y.push(obj[q2])
}
arr.push(x)
arr.push(y)
return arr;
}
i couldn't figure out how can i make the object dynamically.
If you want to generate the objects keys dynamically, you can compute them by using square brackets where the key(s) would go.
For your case, you can replace this:
if(p[1]== ">"){p[1]=gt}
obj = {
$and:[
{p[0]: {$p[1]: p[3}}
]
}
with this:
if (p[1] === ">") { p[1] = 'gt' }
obj = {
$and:[
{
[p[0]]: {
['$' + p[1]]: p[2]
}
}
]
}
and you will get this object as a result (when using your provided input):
{"$and": [
{
"Grade": {
"$gt": "123"
}
}
]
}
Hope that helps!

How to change a range of array with one value Javascript?

I have an array like below let's say
var myArray = ["1", "", "", "2","3","","","8"];
And I want to fill each " " value with previous not null value
According to that expectation should be like below
var myArray = ["1", "2", "2", "2","3","8","8","8"];
Here what I tried but didn't work
var myArray = ["1", "", "", "2","3","","","8"];
function myFunction() {
let currentEl=myArray [0];
let prevIndex=0;
fruits.map((e,a)=>{
if(e!="" && myArray[a-1]==""){
currentEl=e;
let interval=arrayGenerate(a-currentIndex-1,currentEl);
fruits.splice(currentIndex-1, currentEl+1, interval);
currentIndex=a;
}
})
}
function arrayGenerate(iteration,value){
let arr=[];
for(var i=0;i<iteration;i++){
arr.push(value);
}
return arr;
}
console.log(myArray)
You could map the new values and find the missing following value.
var array = ["1", "", "", "2", "3", "", "", "8"],
result = array.map((v, i, a) => v || a.find((w, j) => j > i && w));
console.log(result);
A solution with the same array, by looping from the end and storing the last value.
var array = ["1", "", "", "2", "3", "", "", "8"],
i = array.length,
value;
while (i--) {
if (array[i]) value = array[i];
else array[i] = value;
}
console.log(array);
I have done it like this. I loop over and awlays check the next element if its falsy and not the last element.
var myArray = ["1", "", "", "2","3","","","8"];
function fillArr(arr){
for(let i = arr.length - 1; i >= 0; i--){
if(!arr[i - 1] && i != arr.length){
arr[i - 1] = arr[i];
}
}
return arr;
}
let result = fillArr(myArray);
console.log(result);
You can make use of a stack array to stack indices of null items and then unstack them whenever you encounter a non null item in myArray. (stack is not a reserved keyword so you can call it anything) :
var stack = []
for(var i = 0; i < myArray.length; i++){
if(myArray[i] === "")
stack.push(i);
else if(stack.length !== 0){
for(var j = stack.length - 1 ; j > =0; j--){
myArray[stack[j]] = myArray[i];
stack.splice(j,1);
}
}
}
It's interesting how many different ways this can be done. Just another slightly ugly way to do the same thing:
const fill = (arr, lastVal) => (
arr.reverse()
.map(el => el.length > 0 ? lastVal = el : lastVal)
.reverse()
);
console.log(fill(["1", "", "", "2","3","","","8"]));

Comparing two arrays and push in another array wrong position element

I got two arrays, both type string :
var correctAnswers = ["0", "1", "2", "3", "4", "5"];
and second :
var finalArray = ["0", "1", "4", "3", "5", "2"];
I would like to compare them and and if not match second with first to extract elements and push them in another array, like this :
finalArray = ["0", "1", "3"];
var toChange = ["4", "5", "2"];
You could use jQuery map method too:
var toChange = $.map(finalArray, function(v, k){
return correctAnswers[k] !== v ? v: null;
});
finalArray = $.map(finalArray, function(v, k){
return correctAnswers[k] === v ? v: null;
});
DEMO
Or using array.prototype.filter():
var toChange = finalArray.filter(function(v, k){
return correctAnswers[k] !== v;
});
finalArray = finalArray.filter(function(v, k){
return correctAnswers[k] === v;
});
filter DEMO
var toChange = [];
for (var i = finalArray.length - 1; i >= 0; i--) {
if (finalArray[i] !== correctAnswers[i]) {
toChange.push(finalArray[i]);
finalArray.splice(i, 1);
}
}
The key to this is iterating down from the length to 0, rather than up from 0 to the length as usual. This is because splice changes the indexes of all the elements after the element being removed, so normal iteration would skip an element after each splice.
This will do it:
http://jsfiddle.net/XiozZe/NkM6s/
var correctAnswers = ["0", "1", "2", "3", "4", "5"];
var finalArray = ["0", "1", "4", "3", "5", "2"];
var correctFinal = [];
var toChange = [];
for(var i = 0; i < correctAnswers.length; i++){
if(correctAnswers[i] === finalArray[i]){
correctFinal[correctFinal.length] = finalArray[i];
}
else{
toChange[toChange.length] = finalArray[i];
}
}
First you've got to define your variables
// Define your variables
var correctAnswers = ["0", "1", "2", "3", "4", "5"];
var answers = ["0", "1", "4", "3", "5", "2"];
var finalArray = [];
var toChange = [];
Then you create a loop, which loops over the Answers array.
// comparing them could be done with a simple loop
for (var i = 0; i<answers.length; i++) {
if (correctAnswers[i] == answers[i]) { //if they're equal, push the value into the final array
finalArray.push(answers[i]);
} else { // if not, push them into the toChange array
toChange.push(answers[i]);
}
}
This will give you toChange = [0, 1, 3]
If you want toChange = [0, 1] you've got to change it to
toChange = answers.slice(0);
for (var i = 0; i<correctAnswers.length; i++) {
if (correctAnswers[i] == Answers[i]) { //if they're equal, push the value into the final array and remove the first value from the toChange array
finalArray.push(Answers[i]);
toChange.shift();
} else { // if not, break
break;
}
}
Fiddle

sort by number of occurrence(count) in Javascript array

I am new to Jquery and Javascript. Can someone please help me with Jquery sorting based on number of occurrence(count) in array. I tried various sorting methods but none of them worked.
I have an array in Javascript which is
allTypesArray = ["4", "4","2", "2", "2", "6", "2", "6", "6"]
// here 2 is printed four times, 6 is printed thrice, and 4 is printed twice
I need output like this
newTypesArray = ["2","6","4"]
I tried
function array_count_values(e) {
var t = {}, n = "",
r = "";
var i = function (e) {
var t = typeof e;
t = t.toLowerCase();
if (t === "object") {
t = "array"
}
return t
};
var s = function (e) {
switch (typeof e) {
case "number":
if (Math.floor(e) !== e) {
return
};
case "string":
if (e in this && this.hasOwnProperty(e)) {
++this[e]
} else {
this[e] = 1
}
}
};
r = i(e);
if (r === "array") {
for (n in e) {
if (e.hasOwnProperty(n)) {
s.call(t, e[n])
}
}
}
return t
}
6: 3
}
output is
{4: 2, 2: 6, 6:3}
I don't think there's a direct solution in one step and of course it's not just a sort (a sort doesn't remove elements). A way to do this would be to build an intermediary map of objects to store the counts :
var allTypesArray = ["4", "4","2", "2", "2", "6", "2", "6", "6"];
var s = allTypesArray.reduce(function(m,v){
m[v] = (m[v]||0)+1; return m;
}, {}); // builds {2: 4, 4: 2, 6: 3}
var a = [];
for (k in s) a.push({k:k,n:s[k]});
// now we have [{"k":"2","n":4},{"k":"4","n":2},{"k":"6","n":3}]
a.sort(function(a,b){ return b.n-a.n });
a = a.map(function(a) { return a.k });
Note that you don't need jQuery here. When you don't manipulate the DOM, you rarely need it.
Just adding my idea as well (a bit too late)
var allTypesArray = ["4", "4", "2", "2", "2", "6", "2", "6", "6"];
var map = allTypesArray.reduce(function(p, c) {
p[c] = (p[c] || 0) + 1;
return p;
}, {});
var newTypesArray = Object.keys(map).sort(function(a, b) {
return map[b] - map[a];
});
console.log(newTypesArray)
I don't think jquery is needed here.
There are several great answers to this question already, but I have found reliability to be an issue in some browsers (namely Safari 10 -- though there could be others).
A somewhat ugly, but seemingly reliable, way to solve this is as follows:
function uniqueCountPreserve(inputArray){
//Sorts the input array by the number of time
//each element appears (largest to smallest)
//Count the number of times each item
//in the array occurs and save the counts to an object
var arrayItemCounts = {};
for (var i in inputArray){
if (!(arrayItemCounts.hasOwnProperty(inputArray[i]))){
arrayItemCounts[inputArray[i]] = 1
} else {
arrayItemCounts[inputArray[i]] += 1
}
}
//Sort the keys by value (smallest to largest)
//please see Markus R's answer at: http://stackoverflow.com/a/16794116/4898004
var keysByCount = Object.keys(arrayItemCounts).sort(function(a, b){
return arrayItemCounts[a]-arrayItemCounts[b];
});
//Reverse the Array and Return
return(keysByCount.reverse())
}
Test
uniqueCountPreserve(allTypesArray)
//["2", "6", "4"]
This is the function i use to do this kind of stuff:
function orderArr(obj){
const tagsArr = Object.keys(obj)
const countArr = Object.values(obj).sort((a,b)=> b-a)
const orderedArr = []
countArr.forEach((count)=>{
tagsArr.forEach((tag)=>{
if(obj[tag] == count && !orderedArr.includes(tag)){
orderedArr.push(tag)
}
})
})
return orderedArr
}
const allTypesArray = ["4", "4","2", "2", "2", "6", "2", "6", "6"]
const singles = [...new Set(allTypesArray)]
const sortedSingles = singles.sort((a,b) => a - b)
console.log(sortedSingles)
Set objects are collections of values. A value in the Set may only occur once; it is unique in the Set's collection.
The singles variable spreads all of the unique values from allTypesArray using the Set object with the spread operator inside of an array.
The sortedSingles variable sorts the values of the singles array in ascending order by comparing the numbers.
Not sure if there's enough neat answers here, this is what I came up with:
Fill an object with counts for each of the elements:
let array = ['4', '4', '2', '2', '2', '6', '2', '6', '6'];
let arrayCounts = {}
for (j in array) arrayCounts[array[j]] ? arrayCounts[array[j]].count++ : arrayCounts[array[j]] = { val: array[j], count: 1 };
/* arrayCounts = {
'2': { val: '2', count: 4 },
'6': { val: '4', count: 2 },
'4': { val: '6', count: 3 }
} */
For the values in that new object, sort them by .count, and map() them into a new array (with just the values):
let sortedArray = Object.values(arrayCounts).sort(function(a,b) { return b.count - a.count }).map(({ val }) => val);
/* sortedArray = [ '2', '6', '4' ] */
Altogether:
let arrayCounts = {}
for (j in array) arrayCounts[array[j]] ? arrayCounts[array[j]].count++ : arrayCounts[array[j]] = { val: array[j], count: 1 };
let sortedArray = Object.values(arrayCounts)
.sort(function(a,b) { return b.count - a.count })
.map(({ val }); => val);
var number = [22,44,55,11,33,99,77,88];
for (var i = 0;i<number.length;i++) {
for (var j=0;j<number.length;j++){
if (number[j]>number[j+1]) {
var primary = number[j];
number[j] = number[j+1];
number[j+1] = primary;
}
}
}
document.write(number);

Javascript: Parse array like search querystring

This is a string i have in my javascript
var searchString = City=20&Region=67&&Interests[8]=8&Interests[13]=13&Interests[4]=4&Duration[1]=Full+Day+Tour&Duration[3]=Evening+Tour&Duration[5]=2+Day+Short+Break&Departs[Fri]=Fri&Departs[Sat]=Sat&Departs[Sun]=Sun&TourLanguages=1&action_doSearch=Update
and i have a function
function loadDataFrom(request){
//if request if empty then return
if(request == "")
return;
var request = decodeURIComponent(request);
//if we get there then its likely we have a search query to process
var searchCriteria = request.split('&');
var hash = {};
for(var i = 0; i < searchCriteria.length; i++) {
var val = searchCriteria[i].split('=');
//we can safely ignore the "view" and 'action_doSearch' becuase they are not searched on
if(unescape(val[0]) === 'view' || unescape(val[0]) === 'action_doSearch')
continue;
//filter objects without any values
if(val[1] != '')
//add the names and values to our object hash
hash[unescape(val[0])] = unescape(val[1]);
}
//iterate over the hash objects and apply the current selection
$.each(hash, function(index, value) {
switch (index) {
case 'City':
case 'Region':
case 'TourLanguages':
//do stuff;
break;
case 'Duration[]':
case 'Departs[]':
//do something esle
default:
break;
}
});
};
that parses the URL parameters into an objecct hash with the following values.
City: "20"
Region: "67"
Departs[Fri]: "Fri"
Departs[Sat]: "Sat"
Departs[Sun]: "Sun"
Duration[1]: "Full+Day+Tour"
Duration[3]: "Evening+Tour"
Duration[5]: "2+Day+Short+Break"
Interests[4]: "4"
Interests[8]: "8"
Interests[13]: "13"
TourLanguages: "1"
but what i'd really like to do is to seperate the url into array like values like so
City: "20"
Region: "67"
Departs: ["Fri","Sat","Sun"]
Duration: ["Full+Day+Tour", "Evening+Tour", "2+Day+Short+Break"]
Interests: ["4", "8", "13"]
TourLanguages: "1"
Any help/pointers on this problem is greatly appreciated. Thanks in Advance
For something like this, to make it easier on myself I would write a RegExp to get the parts, then do some if logic to decide how to construct the Object.
var searchString = "City=20&Region=67&&Interests[8]=8&Interests[13]=13&Interests[4]=4&Duration[1]=Full+Day+Tour&Duration[3]=Evening+Tour&Duration[5]=2+Day+Short+Break&Departs[Fri]=Fri&Departs[Sat]=Sat&Departs[Sun]=Sun&TourLanguages=1&action_doSearch=Update",
o = {};
('&' + searchString)
.replace(
/&([^\[=&]+)(\[[^\]]*\])?(?:=([^&]*))?/g,
function (m, $1, $2, $3) {
if ($2) {
if (!o[$1]) o[$1] = [];
o[$1].push($3);
} else o[$1] = $3;
}
);
o; /*
{
"City": "20",
"Region": "67",
"Interests": ["8", "13", "4"],
"Duration": ["Full+Day+Tour", "Evening+Tour", "2+Day+Short+Break"],
"Departs": ["Fri", "Sat", "Sun"],
"TourLanguages": "1",
"action_doSearch": "Update"
} */
I would do it this way:
var str = 'City=20&Region=67&&Interests[8]=8&Interests[13]=13&Interests[4]=4&Duration[1]=Full+Day+Tour&Duration[3]=Evening+Tour&Duration[5]=2+Day+Short+Break&Departs[Fri]=Fri&Departs[Sat]=Sat&Departs[Sun]=Sun&TourLanguages=1&action_doSearch=Update',
strsplit = str.split(/&+/),
o = {};
for (var i = 0, l = strsplit.length; i < l; i++) {
var r = strsplit[i].match(/^([^=\[\]]+)(?:\[[^\]]+\])?=(.*)$/);
if (o[r[1]] === undefined) {
o[r[1]] = r[2];
} else if (o[r[1]].push) {
o[r[1]].push(r[2]);
} else {
o[r[1]] = [o[r[1]], r[2]];
}
}
This is a perfect scenario to use Map-Reduce and I recommend you to use underscore.js to implement something simple, elegant and more readable solution.
var m = _.map(searchString.split('&'), function (item) {
var parts = item.split('='), names = parts[0].split('[');
return [names[0], parts[1]];
});
var result = _.reduce(m, function(memo, item){
var key = item[0], value = item[1];
if(memo[key] === undefined) memo[key] = [value]
else memo[key].push(value)
return memo;
}, {});
console.log(result);

Categories

Resources