search value of index in indexed array javascript - javascript

Let's take an indexed (associative) array as shown below
var gh = { pop: 'apple', jim: 'orange', john: 'ball', sim: 'oran' }
How can I search this array to find the indexes where the value is like 'ora'?
Example:
If I given input ora I have to get indexes jim and sim as output.

So you're needing the keys of Object whose value matches certain pattern. You could use [].filter on Object.keys(gh) which returns an Array of keys for the Object passed in.
var str = "ora", gh = { pop: 'apple', jim: 'orange', john: 'ball', sim: 'oran' };
var output = Object.keys(gh).filter(function(key){
return gh[key].indexOf(str) == 0; // condition
});
Use the condition gh[key].indexOf(str) > -1 if str can appear anywhere in the String not just at the start. You could see the contents of output Array by logging it
console.log(output);
If you want to get them as Array of {key:value} as you've stated in the comments, you could do
var result = output.map(function(k){
var obj = {};
obj[k] = gh[k];
return obj;
});

Related

How can i solve this scenario without nested for loop in javascript

var selectedRows = gridOptions.api.getSelectedRows(); //this is an array
selectedRows.forEach(function(selectedRow, index) {
if (dataSampleAfterUpdate.length == 0) {
dataSampleAfterUpdate.push(selectedRow);
}
for (var x = 0; x < dataSampleAfterUpdate.length; x++) {
if (dataSampleAfterUpdate[x].Id == selectedRow.Id) {
dataSampleAfterUpdate[x] = selectedRow;
} else {
dataSampleAfterUpdate.push(selectedRow);
}
}
});
Actually this code works for 10 or 20 records. But in case of 500 records the page hangs.
Is there any alternate way of using nested for loop?Please help
You have an O(n^2) complexity algorithm. Instead of array, you can keep track of your visited items in an object, so the lookup can be done in O(1) complexity and the need for inner for loop is eliminated.
To the best of my understanding of your code you likely need the following simplified code that runs in O(n) time:
var selectedRows = gridOptions.api.getSelectedRows(); //this is an array
var obj = Object.fromEntries(dataSampleAfterUpdate.map(e => [e.Id, e]));
selectedRows.forEach( function(selectedRow, index) {
obj[selectedRow.Id] = selectedRow;
});
dataSampleAfterUpdate = Object.values(obj);
Here is an improvement to an earlier answer:
var selectedRows = gridOptions.api.getSelectedRows(); //this is an array
var arr = [...dataSampleAfterUpdate, ...selectedRows];
var obj = Object.fromEntries(arr.map(e => [e.Id, e]));
dataSampleAfterUpdate = Object.values(obj);
This first combines the two arrays into one single array arr. Then creates an object by grouping the array by their ids, to remove duplicates. By design it replaces the previous values by the one encountered next.
To understand this better you can expand and run the code snippet below. Individual steps are explained.
var dataSampleAfterUpdate = [{Id: 1, Data: "a"}, {Id: 2, Data: "b"}, {Id: 3, Data: "c"}];
var selectedRows = [{Id: 2, Data: "bb"}, {Id: 4, Data: "dd"}];
// Combine the arrays into a nested array with eventual key value pairs (key = id).
var arr = [...dataSampleAfterUpdate, ...selectedRows];
console.log("Log 1:", JSON.stringify(arr));
// Converts into a nested array with eventual key value pairs (key = id).
var temp = arr.map(e => [e.Id, e]);
console.log("Log 2:", JSON.stringify(temp));
// Converts key value pair to object. Removes duplicate ids. By design object can only hold one value per key.
var obj = Object.fromEntries(temp);
console.log("Log 3:", JSON.stringify(obj));
// Converts back to array of values.
dataSampleAfterUpdate = Object.values(obj);
console.log("Log 4:", JSON.stringify(dataSampleAfterUpdate));

How to enter a string to an array to a given position?

The condition is such that I have to enter a string to an array to a given position
such that all the pre position if not exist should be made to be empty strings.
example;
var array = []; // now I want to enter a string 'hello' at index 2
now the array should look like:
array = [ '','','hello']; //now lets say I want to enter a string 'world' at index 4
so the array should become:
array = [ '','','hello','','world'];
Is there a way to do this?
or do i have a better option to enter a string and and its position?
Please enlighten me.. :)
Something like this should do the trick. The function takes three arguments: the target array, the index (0-based) and the value. Just iterate from the finish of you array to the new position and add "" to each entry, then, after the loop, enqueue the desired string. Here's the fiddle.
let a = ['', '', 'Hello'];
function addStringAtPosition(
array,
key,
value
) {
for (let i = array.length; i < key; i++) {
array[i] = '';
}
array[key] = value;
}
addStringAtPosition(a, 5, 'World!');
First find out how many additional elements need to add ''
push these new elements to array.
push the required value at end.
PS: Assumed the index always higher than the array length. We can add conditions to cover those cases as well.
const insert = (arr, value, index) => {
arr.push(...new Array(index - arr.length).fill(""));
arr.push(value);
return arr;
};
const array = [];
insert(array, "hello", 2);
console.log(array);
insert(array, "world", 4);
console.log(array);

Forcing javascript key integer fills array with null

I am creating an array in Javascript where the product id is used for the key. As the key is numeric, the array is filling gaps with null.
So for example, if I had only two products and their ids were 5 and 7, I would do something like:
var arr = []
arr[5] = 'my first product';
arr[7] = 'my second product';
This array is then passed to a PHP script but upon printing the array, I get the following;
Array (
[0] = null
[1] = null
[2] = null
[3] = null
[4] = null
[5] = My first product
[6] = null
[7] = My second product
)
my ID numbers are actually 6 digits long, so when looping over the array, there are 100,000 iterations, even if I actually only have two products.
How can I create the array so the null values are not entered? I thought of making the key a string instead but as the array is build dynamically, I am not sure how to do that.
var arr = [];
for(var i=0; i<products.length; i++)
{
array[products[i].id] = products[i].name;
}
Thanks
For iterating the array, you could use Array#forEach, which skips sparse items.
var array = [];
array[5] = 'my first product';
array[7] = 'my second product';
array.forEach(function (a, i) {
console.log(i, a);
});
For better organisation, you could use an object, with direct access with the given id.
{
5: 'my first product',
7: 'my second product'
}
Forcing javascript key integer fills array with null
You are declaring an empty array and then setting values into 6th and 8th element in the array. That leaves the values of other elements as null.
If you don't intend to push items into array, i.e. use objects. Something like,
var obj = {};
obj[5] = "my first product";
obj[7] = "my second product";
This means the object created is:
obj = {"5":"my first product","7":"my second product"}
var arr = []
arr[5] = 'my first product';
arr[7] = 'my second product';
let result = arr.filter(ar => ar != null);
console.log(result);

Add item to array by key in JavaScript

I need to group item having same name property and increase their number. I try to assign to new array and check existed item by key. It works fine when I use this solution in PHP, but in JavaScript it doesn't.
I have searched some similar questions, but I don't know why it doesn't work.
var orgArr = [
{name: 'abc', number: 3},
{name: 'xyz', number: 2},
{name: 'abc', number: 5}
];
var result = []; //work if result = {};
for (var i = 0; i < orgArr.length; i++) {
if (!result[orgArr[i].name]) {
result[orgArr[i].name] = orgArr[i]; //assign new
} else {
result[orgArr[i].name].number += orgArr[i].number; //increase number if name exist in result array
}
}
alert(JSON.stringify(result)); //expect array 2 item but it's empty array
console.log(result); //Will have result 2 item when I view console window
var orgArr = [
{name: 'abc', number: 3},
{name: 'xyz', number: 2},
{name: 'abc', number: 5}
];
var result = []; //work if result = {};
var tempArray = []; // used to store unique name to prevent complex loop
orgArr.forEach(function(item){
if($.inArray(item.name, tempArray)< 0){// unique name
result.push(item);
tempArray.push(item.name);
}
else{
var indexNew = $.inArray(item.name, tempArray);
result[indexNew].number += item.number;
}
});
alert(JSON.stringify(result)); //expect array 2 item but it's empty array
console.log(result); //Will have result 2 item when I view console window
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
E/ My previous answer was incorrect.
Well.. yes...
[] designates an array. An array holds everything by integer values. You're trying to feed it a string value (orgArr[x].name) and since its just an array, it discards it as a bad call.
{} is an object. Objects can have string indexes.
var result = []; //work if result = {};
Why can't result be {}?
if you want it to work, make result = {} not []
an array is not a key value store. It still will take key values, and will store them on the array object. But when stringify encounters your array, it determines it is an array and then trys to iterate the array, and your array appears empty. so you get nothing in your output.
You get empty array it's because by default JSON.stringify failed to convert your array to json string.
By default JSON.stringify converts int-based index array to json string but you are using orgArr[i].name which is a string as array index that the cause alert() show empty array.
Can you explain why would you want to convert json array to an array with string index. It's always better to use json array if you want a string as key/index.
For more information about JSON.stringify

Why does JavaScript map function return undefined?

My code
var arr = ['a','b',1];
var results = arr.map(function(item){
if(typeof item ==='string'){return item;}
});
This gives the following results
["a","b",undefined]
I don't want undefined in the results array. How can I do it?
You aren't returning anything in the case that the item is not a string. In that case, the function returns undefined, what you are seeing in the result.
The map function is used to map one value to another, but it looks like you actually want to filter the array, which a map function is not suitable for.
What you actually want is a filter function. It takes a function that returns true or false based on whether you want the item in the resulting array or not.
var arr = ['a','b',1];
var results = arr.filter(function(item){
return typeof item ==='string';
});
Filter works for this specific case where the items are not modified. But in many cases when you use map you want to make some modification to the items passed.
if that is your intent, you can use reduce:
var arr = ['a','b',1];
var results = arr.reduce((results, item) => {
if (typeof item === 'string') results.push(modify(item)) // modify is a fictitious function that would apply some change to the items in the array
return results
}, [])
Since ES6 filter supports pointy arrow notation (like LINQ):
So it can be boiled down to following one-liner.
['a','b',1].filter(item => typeof item ==='string');
You can implement like a below logic.
Suppose you want an array of values.
let test = [ {name:'test',lastname:'kumar',age:30},
{name:'test',lastname:'kumar',age:30},
{name:'test3',lastname:'kumar',age:47},
{name:'test',lastname:'kumar',age:28},
{name:'test4',lastname:'kumar',age:30},
{name:'test',lastname:'kumar',age:29}]
let result1 = test.map(element =>
{
if (element.age === 30)
{
return element.lastname;
}
}).filter(notUndefined => notUndefined !== undefined);
output : ['kumar','kumar','kumar']
My solution would be to use filter after the map.
This should support every JS data type.
example:
const notUndefined = anyValue => typeof anyValue !== 'undefined'
const noUndefinedList = someList
.map(// mapping condition)
.filter(notUndefined); // by doing this,
//you can ensure what's returned is not undefined
You only return a value if the current element is a string. Perhaps assigning an empty string otherwise will suffice:
var arr = ['a','b',1];
var results = arr.map(function(item){
return (typeof item ==='string') ? item : '';
});
Of course, if you want to filter any non-string elements, you shouldn't use map(). Rather, you should look into using the filter() function.
If you have to use map to return custom output, you can still combine it with filter.
const arr = ['a','b',1]
const result = arr.map(element => {
if(typeof element === 'string')
return element + ' something'
}).filter(Boolean) // this will filter out null and undefined
console.log(result) // output: ['a something', 'b something']
var arr = ['a','b',1];
var results = arr.filter(function(item){
if (typeof item ==='string') {return item;}
});
If you use it like this, your problem will be solved.
Also, you will have a clean and short code
var _ = require('lodash'); //but first, npm i lodash --save
var arr = ['a','b',1];
var results = _.compact(
_.map(arr, function(item){
if(_.isString(item)){return item;}
}
); //false, null, undefined ... etc will not be included
with ES6...
const _ = require('lodash'); //but first, npm i lodash --save
const arr = ['a','b',1];
const results = _.compact(
_.map(arr, item => {
if(_.isString(item)){return item;}
}
);
I run into this quite frequently where the type after filtering will still be string | number. So, to expand upon these solutions and include type safety you can use a user-defined type guard.
https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
const result = ['a','b',1].filter((item) => typeof item ==='string');
// result is typed as (string | number)[]
Better type safety using user-defined type guard
const result = ['a','b',1].filter((item): item is string => typeof item ==='string');
// result is now typed as string[]
The problem:
the issue is arr.map() will do a full iteration of arr array length, i.e. map() method will loop as much as the length of arr is, no matter what condition you have inside it, so if you defined a condition inside it e.g. if(typeof item ==='string'){return item;} even if the condition is not happening, the map() will be forced to keep looping until finishing the looping of the whole arr so it will give you undefined for the rest of elements if the condition is not met.
The solutions:
Solution One: if you want to return the whole item in the array when the condition is met, you can use arr.filter() so the filter will return the whole item for the iteration e.g. if you have array of objects like bellow
const arr = [{name: "Name1", age: 25}, {name: "Name2", age: 30}, {name: "Name3", age: 25}]
and you want to return the whole objects when the condition is met like example below
const filteredItems = arr.filter((item)=>{if(item.age === 25){return true}})
console.log(filteredItems) //results: [{name: "Name1", age: 25}, {name: "Name3", age: 25}]
conclusion: filter() method returns an array of the whole items in it if the condition is met.
Solution Two: if you want to return only a specific data of the objects (or the whole object or any shape of data) in array i.e. if you want to return only the names in array without the ages, you can do this
const namesOnly = arr.map((item)=>{if(item.age === 25){return item.name}})
console.log(namesOnly) //results: ["Name1, udefined, "Name3"]
now to remove the undefined you just use filter() method on the results like below
const namesOnly = arr.map((item)=>{if(item.age === 25){return item.name}}).filter((item)=> !!item)
console.log(namesOnly) //results: ["Name1, "Name3"]
conclusion: map() method returns an array of specifically defined data in the return, and returns undefined if the condition is not met. so then we can use filter() method to remove the undefined.
You can filter records with .map easily using below example code
const datapoints = [
{
PL_STATUS: 'Packetloss',
inner_outerx: 'INNER',
KPI_PL: '97.9619'
},
{
PL_STATUS: 'Packetloss',
inner_outerx: 'OUTER',
KPI_PL: '98.4621',
},
{
PL_STATUS: 'Packetloss',
inner_outerx: 'INNER',
KPI_PL: '97.8770',
},
{
PL_STATUS: 'Packetloss',
inner_outerx: 'OUTER',
KPI_PL: '97.5674',
},
{
PL_STATUS: 'Packetloss',
inner_outerx: 'INNER',
KPI_PL: '98.7150',
},
{
PL_STATUS: 'Packetloss',
inner_outerx: 'OUTER',
KPI_PL: '98.8969'
}
];
const kpi_packetloss_inner: string[] = [];
datapoints.map((item: { PL_STATUS: string; inner_outerx: string; KPI_PL: string }) => {
if (item.PL_STATUS === 'Packetloss' && item.inner_outerx === 'INNER') {
kpi_packetloss_inner.push(item.KPI_PL);
}
})
console.log(kpi_packetloss_inner);
Map is used when you want to produced new modified array from the original array.
the simple answer may be for someone
var arr = ['a','b',1];
var results = arr.filter(function(item){
// Modify your original array here
return typeof item ==='string';
}).filter(a => a);

Categories

Resources