JS array index number into value with string replace - javascript

I have a multidimentional array:
(3) [Array(1), Array(1), Array(1)]
0:["('idDocDetail','0','$createdBy')"]
1:["('idDocDetail','2','$createdBy'),('idDocDetail','4','$createdBy')"]
2:["('idDocDetail','0','$createdBy')"]
I need to replace the string value idDocDetail with the index number, like this.
(3) [Array(1), Array(1), Array(1)]
0:["('0','0','$createdBy')"]
1:["('1','2','$createdBy'),('1','4','$createdBy')"]
2:["('2','0','$createdBy')"]
I'm trying to use replace, but I got the replace is not a function error.
array.forEach(function(item, index) {
return item.toString().replace('idDocDetail', index);
});
what am I doing wrong? Replace is the right way to do this?

I do recommend you to learn to perform changes in immutable manner. This is where Array.prototype.map plays well
const data = [
["('idDocDetail','0','$createdBy')"],
["('idDocDetail','2','$createdBy'),('idDocDetail','4','$createdBy')"],
["('idDocDetail','0','$createdBy')"]
]
const modified = data.map((item, index) =>
item.map(str => str.replace(/idDocDetail/g, index ))
)
modified.forEach(x => console.log(JSON.stringify(x)))

Here, this works for your code structure. It uses map() to produce a new array by just replacing the string of interest with the index.
EDIT: Added a nested map for clarity + regular expression to find all instances of 'idDocDetail' in the string, not just the first one. replace method when given a raw string value only handles the first instance of a string occurring.
const array = [["('idDocDetail','0','$createdBy')"],
["('idDocDetail','2','$createdBy'),('idDocDetail','4','$createdBy')"],
["('idDocDetail','0','$createdBy')"]]
var find = 'idDocDetail';
var re = new RegExp(find, 'g');
let newArray = array.map((val, i) => val.map(string => {
return string.replace(re, i)
}))
console.log(newArray)

You can loop over your array and edit it.
let array = [
["('idDocDetail','0','$createdBy')"],
["('idDocDetail','2','$createdBy'),('idDocDetail','4','$createdBy')"],
["('idDocDetail','0','$createdBy')"],
];
array.forEach((e, i) => {
array[i] = [e[0].replace(/idDocDetail/g, i)];
});
console.log(array);

You can not replace an item by calling a method on the item being replaced. Instead you need to call it on the array. You can do it this way:
for (var i=0; i<array.length; i++) {
array[i][0] = i;
}

forEach ignores the return of the callback. You need to assign to the original array at the current index.
var array = [
["('idDocDetail','0','$createdBy')"],
["('idDocDetail','2','$createdBy'),('idDocDetail','4','$createdBy')"],
["('idDocDetail','0','$createdBy')"]
];
array.forEach(function(item, index) {
array[index] = item.map(s => s.replace('idDocDetail', index));
});
console.log(array);

Related

Original index position after filtering an array

I have an array that is filtered based on what the user types into a search box..
var x = ["Apple","Pear","Pineapple"];
var value = e.target.value;
var regex = new RegExp(`^${value}`, 'i');
var filtered = x.sort().filter(v => regex.test(v));
If I were to type "P" into the search box the console would print
["Pear","Pineapple"]
What I need however is another array of the original index position of Pear and Pineapple that would print the following
[1,2]
How would I go about achieving this?
You can do that in a single shot using reduce (read more about reduce here).
There is no need to filter, you can just generate another array, keep track of the index of the currently looped item (assuming you want the sorted index).
If you don't want the sorted index, just remove .sort. Not sure why it's there in the first place.
This solution requires a single iteration, which should be optimal (as long as you remove the unneeded sort).
var x = ["Apple","Pear","Pineapple"];
var value = 'P';
var regex = new RegExp(`^${value}`, 'i');
var filtered = x.sort().reduce((acc, next, i) => { // acc is the current accumulator (initially an empty array), next is looped item, i is item's index (what you want in the result).
return regex.test(next) && acc.push(i), acc // <-- if the regex test is successfull, `i` is pushed to the accumulator. In both cases (so, even if the regex fails) the accumulator is returned for the next iteration.
}, []); // <-- [] is the initial value of `acc`, which is a new empty array.
console.log(filtered);
Instead of filtering the array, filter the keys of the array instead:
var x = ["Apple","Pear","Pineapple"],
value ="P",
regex = new RegExp(`^${value}`, 'i'),
filtered = [...x.keys()].filter(i => regex.test(x[i]));
console.log(filtered)
keys() method returns a Array Iterator. So, you need to use spread syntax or Array.from() to convert it to an array
You could get first the value/index pairs, filter and get either the values or indices.
Intead of a RegExp, you could use String#startsWith, which has no problems of characters with special meanings.
var array = ["Apple", "Pear", "Pineapple"],
value = 'P',
filtered = array
.sort()
.map((v, i) => [v, i])
.filter(([v]) => v.startsWith(value)),
values = filtered.map(([v]) => v),
indices = filtered.map(([, i]) => i);
console.log(values);
console.log(indices);
You can get your indexes with indexOf() from the original array like so:
const x = ["Apple","Pear","Pineapple"];
var regex = new RegExp(`^P`, 'i');
const filtered = x.sort().filter(v => regex.test(v));
const filteredIndexes = filtered.map(v => x.indexOf(v));
console.log(filtered);
console.log(filteredIndexes);
You could also use reduce to do it all in one iteration like the so:
const x = ["Apple","Pear","Pineapple"];
var regex = new RegExp(`^P`, 'i');
const [filtered, filteredIndexes] = x.sort().reduce((acc, val, i) => {
// If the regex fits, add to the arrays
if(regex.test(val)) {
// Adding to the array via array spread operator
acc = [[...acc[0], val],[...acc[1], i]];
}
return acc;
}, [[],[]]); // Initial value of accumulator
console.log(filtered);
console.log(filteredIndexes);

Lodash: Extract property, split array, get unique values

In my JS project, I am using Lodash library to Extract property, split array, get unique values.
var taskobj = [
{'taskno':'a', 'team':'1,2'},
{'taskno':'b', 'team':'3,4'},
{'taskno':'c', 'team':'2,4'},
];
//Looping through the object to convert string to array
_.forEach(taskobj, function(value, key) {
taskobj[key].team = _.split(taskobj[key].team,',');
});
// using _.map to extract team and return array
// using _.flatten to flatten array
// using _.uniq to get unique values from flattned array.
return _.uniq(_.flatten(_.map(taskobj,'team')));
// logs - [1,2,3,4]
Is this the most efficient way to achieve this?
you can use reduce and start with a new Set() and add the values of team every time ( then convert it back to an array with the spread operator )
var taskobj = [
{'taskno':'a', 'team':'1,2'},
{'taskno':'b', 'team':'3,4'},
{'taskno':'c', 'team':'2,4'},
];
var result = [...taskobj.reduce((acc, {team}) => {
team.split(',').forEach(e => acc.add(e))
return acc
}, new Set())]
console.log(result)
This can be achieved by using lodash#flatMap with an iteratee that splits the team string into an array, which is then flattened by the mentioned function and then use lodash#uniq to get the final result.
var result = _.uniq(_.flatMap(taskobj, ({ team }) => team.split(',')));
var taskobj = [
{'taskno':'a', 'team':'1,2'},
{'taskno':'b', 'team':'3,4'},
{'taskno':'c', 'team':'2,4'},
];
var result = _.uniq(_.flatMap(taskobj, ({ team }) => team.split(',')));
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Use simpler version
try this
var teams = [];
var taskobj = [
{'taskno':'a', 'team':'1,2'},
{'taskno':'b', 'team':'3,4'},
{'taskno':'c', 'team':'2,4'},
];
taskobj.map(obj => {
var teamSplit = obj.team.split(',');
teams = [...teams, ...teamSplit];
})
var uniqTeams = _.uniq(teams);
console.log('teams', teams);
console.log('uniqTeams', uniqTeams)
JsBin link
http://jsbin.com/bedawatira/edit?js,console

Find index of any array using value in string array

a=[
{x:1,y:1,i:"Piechart1"},
{x:2,y:1,i:"Piechart2"},
{x:3,y:1,i:"Piechart3"}
]
str=["Piechart1","Piechart3"];
I want get index by comparing array string.Output in above example should be [0,2]
Could you please let me know how to achieve in lodash ,javascript
Use .map() to map the strings to their index, and .findIndex inside the .map() callback to locate the index of the object.
var a = [{x:1,y:1,i:"Piechart1"},{x:2,y:1,i:"Piechart2"},{x:3,y:1,i:"Piechart3"}];
var str = ["Piechart1","Piechart3"];
var res = str.map(s => a.findIndex(o => o.i == s));
console.log(res);
You can chain .filter(idx => idx != -1) on the end if there's any chance of one of the strings not being in the main array.
You can use reduce() method and includes() to check if element exists in another array.
const a = [{"x":1,"y":1,"i":"Piechart1"},{"x":2,"y":1,"i":"Piechart2"},{"x":3,"y":1,"i":"Piechart3"}]
const str = ["Piechart1", "Piechart3"];
const result = a.reduce((r, {i}, ind) => {
return str.includes(i) && r.push(ind), r
}, [])
console.log(result)
maps each value in str to their index in a.
str.map((str) => a.findIndex((ele) => str === ele.i))

JavaScript generate array of strings with inline solution

There simple code:
var arr = [];
for(var i = 0; i < 10; i++){
arr.push("some string with iterating value "+i);
}
I wonder if there is a one-line solution in which I enter the string and the maximum value and get an array of generated lines.
Try this, if the input is 5, you can have it as N and get the input from user
DEMO
var result = Array.from(new Array(5),(val,index)=> "some string " + index );
console.log(result);
const newArray = [...Array(10)].map((_, i) => `some string with iterating value ${i}`)
console.log(newArray)
You can use a spread operator and create a new array of the length you require, loop (map) over it and return the string. This will create a new array of the length (10) with the string you want in it.
How about making it a reusable function? E.g.
// Replaces '{i}' with the index number
var generateStringArray = (length, string) => Array.from(new Array(length), (val, index) => string.replace('{i}', index))
console.log(generateStringArray(6, "some string {i}"));

Remove last letter from map value

So I'm getting this from backend:
{"Item":{"userEmail":"b","Username":"bUsername","Push":"sdsdsd","Password":"sdsds","Buddy":{"datatype":"SS","contents":{"Drake":"Drake","Ola":"Ola","b":"b","d":"d"}}}}
I use Object.Keys to narrow down the contents to:
Drake,Ola,b,d
Which I then map to give:
[{"id":"Drake"},{"id":"Ola"},{"id":"b"},{"id":"d"}]
Which is then used on my Angular Front-end as .id. I want to remove the last letter from each value i.e leaving Drak,Ol etc. I've tried many ways but have failed, how can I achieve this please so that the id has those values?
EDIT
I also want to now get that value that was cut AND add it such that the end product will be [{"id":"Drak",valueThatWasCut:"e"}]
You could iterate the object's keys and build with the short string a new object.
var data = {"Item":{"userEmail":"b","Username":"bUsername","Push":"sdsdsd","Password":"sdsds","Buddy":{"datatype":"SS","contents":{"Drake":"Drake","Ola":"Ola","b":"b","d":"d"}}}},
ids = Object.keys(data.Item.Buddy.contents).reduce(function (r, k) {
var n = k.slice(0, -1);
return n ? r.concat({ id: n }) : r;
}, []);
console.log(ids);
Perhaps something like :
var arr = [{"id":"Drake"},{"id":"Ola"},{"id":"b"},{"id":"d"}];
var result = arr.map(x => x.id.slice(0,-1));
console.log(result); // [ 'Drak', 'Ol', '', '' ]
Create a temporary contents object and change in that.
Then just set this in the original object. ES6 spread operators would save the rest of data without respecifying all keys and values.
let items = {"Item:{"userEmail":"b","Username":"bUsername","Push":"sdsdsd","Password":"sdsds","Buddy":{"datatype":"SS","contents":{"Drake":"Drake","Ola":"Ola","b":"b","d":"d"}}}};
let contents = items.Item.Buddy.contents;
let contentsNew = Object.keys(contents).map((content) => {
return {[content.substring(0, content.length-1)]: content.substring(0, content.length-1), valueThatWasCut: content[content.length-1]};
});
items = {...items, Item: {...items.Item,Buddy:{...items.Item.Buddy,contents: contentsNew}}};
console.log(items);

Categories