I have a Array, with a series of words that it collects in another function. What I intend is to count and separate those words that are unique and in the event that it is repeated do not count them. I've come this far, but the code stays in the first for. The goal is to count unique words in the array.
let arrayTemp = [];
Array1.forEach((item) => {
if(arrayTemp[0]){
arrayTemp[0] = item.perfilRoot;
}
for(let i = 0; i < arrayTemp.length; i++){
if(item.perfilRoot != arrayTemp[i]){
arrayTemp.push(item.perfilRoot);
}else{
break;
}
}
});
Convert to Set and check size
unique = new Set(YourArray);
console.log(unique.size)
You can try using Set which is an object that lets you store unique values.
const valuesYouWant = Array1.map(item => item.perfilRoot); // new array with values you want from Array1
const uniqueValues = [...new Set(valuesYouWant)]; // new array with unique values from array valuesYouWant
console.log(uniqueValues); // this will log your unique values
console.log(uniqueValues.length); // this will log the length of the new created array holding the unique values
You can consider using a Set.
array = [1,1,2,3,4,4,5];
unique = [...new Set(array)];
console.log (unique.length);
you can use Sets:
let arr = [1, 2, 3, 2, 3, 1]
console.log(new Set(arr).size)
or you can use object like maps to count uniques keys:
let arr = ['dog', 'dog', 'cat', 'squirrel', 'hawk', 'what a good dog'];
let m = {};
// count uniques words in array
arr.forEach(word => m[word] = 1);
// prints uniques counters
console.log('count:', Object.keys(m).length)
Since you only want to count the unique words, Set will not work. The code below looks at the array and only if the word is only found once in Array1 does it add it to arrayTemp
let arrayTemp = [];
Array1.map(a=>a.perfilRoot).forEach((item, index) => {
if (index +1 < Array1.length && Array1.slice(index +1).indexOf(item) === -1) arrayTemp.push(item);
});
console.log(arrayTemp);
console.log('number of unique words', arrayTemp.length);
Related
I have an array, each subarray of which contains different positions in different order:
[
["apple(2)", "banana(5)"],
["peach(3)", "banana(1)"],
["apple(1)"]
]
I need to sort it on JavaScript (ES6) and i expect to get an array like this:
[
["apple(2)", "banana(5)", "peach(0)"],
["apple(0)", "banana(1)", "peach(3)"],
["apple(1)", "banana(0)", "peach(0)"]
]
Order of each subarray should be the same. If subarray don't have some position, i need to add it with 0 value. Can i using something like map() or sort() function or need to compare it manually?
Here is functional programming approach, using a Map and reduce:
const data = [['apple(2)', 'banana(5)'],['peach(3)', 'banana(1)'],['apple(1)'],];
// Create a Map with default values for each name, i.e. with "(0)":
let names = new Map(data.flat().map(item => [item.replace(/\d+/, ""), item.replace(/\d+/, "0")]));
let result = data.map(row =>
[...row.reduce((map, item) =>
map.set(item.replace(/\d+/, ""), item), // Overwrite default
new Map(names) // Start with clone of original Map
).values()]
);
console.log(result);
You have to loop over to get the keys used. You then have to loop over a second time to get the fill in the missing keys. There are many ways of doing it, this is one.
var data = [
["apple(2)", "banana(5)"],
["peach(3)", "banana(1)"],
["apple(1)"]
];
// match string and number
var re = /([^(]+)\((\d+)\)/;
// Loop over and find all of the keys
var grouped = data.reduce((info, subset, index) => {
subset.forEach(item => {
// find the key and count
var parts = item.match(re);
// have we seen this key?
if (!info[parts[1]]) {
// if not create an array
info[parts[1]] = Array(data.length).fill(0);
}
// set the key index with the count
info[parts[1]][index] = parts[2];
})
return info;
}, {});
// loop over the groups and fill in the set
Object.entries(grouped).forEach(([key, counts], colIndex) => {
counts
.forEach((cnt, rowIndex) => {
data[rowIndex][colIndex] = `${key}(${cnt})`;
})
});
console.log(data);
First get the unique words. Then traverse array of arrays to check if the word is present or not. If it is not present then make the word according to your condition and if present then put the original word to the tmp array. At last sort it for each iteration. By the way, I used regex replace method to get the word.
const data = [
['apple(2)', 'banana(5)'],
['peach(3)', 'banana(1)'],
['apple(1)'],
];
const words = [...new Set(data.flat().map((x) => x.replace(/[^a-z]/gi, '')))];
const ret = data.map((x) => {
const tmp = [];
const newX = x.map((y) => y.replace(/[^a-z]/gi, ''));
for (let i = 0, l = words.length; i < l; i += 1) {
if (newX.includes(words[i])) tmp.push(x.shift());
else tmp.push(`${words[i]}(0)`);
}
return tmp.sort();
});
console.log(ret);
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));
This is the tricky one :
please understand my scenario:
I have two array , both array will have equal length always.
I want remove duplicate value in first array and second array will be manipulated according first one.
like if i have array like :
var firstArr = [1,1,4,1,4,5]
var secArr = ['sagar', 'vilas', 'suraj', 'ganesh','more','abhi']
//I want below Output
//[1,4,5] // this is firstArr after manipulation
//['sagar|vilas|ganesh','suraj|more',abhi] // this is secArr after manipulation
// here all duplicate values will be removed from first array
// and at same index second array will be manipulated.
please check my fiddle:
https://jsfiddle.net/abhilash503001/du4fe8ob/86/
You can use Map and reduce
First loop through the first array and map it values as key and take the values from second array's respective index as key
Now you have loop on the map's entries take the key's will be your unique firstArr and to get desired value for second arr you need to join values by |
var firstArray = [1,1,4,1,4,5]
var secArr = ['sagar', 'vilas', 'suraj', 'ganesh','more','abhi']
let op = firstArray.reduce((op,inp,index) => {
if(op.has(inp)){
let val = op.get(inp)
val.push(secArr[index])
op.set(inp, val)
} else {
op.set(inp,[secArr[index]])
}
return op
},new Map())
let {firstArr, secondArr} = [...op.entries()].reduce((op,[first,second])=>{
op.firstArr.push(first)
op.secondArr.push(second.join('|'))
return op
},{firstArr:[],secondArr:[]})
console.log(firstArr)
console.log(secondArr)
This is how I did it.
You first group the texts into arrays and then join them together.
var index_array = [1,1,4,1,4,5]
var text_array = ['sagar', 'vilas', 'suraj', 'ganesh','more','abhi'];
var manipulated_text_array = [];
var manipulated_index_array = [];
var groups = {};
for (let index in index_array) {
if (groups[index_array[index]] == undefined) {
groups[index_array[index]] = [];
}
groups[index_array[index]].push(text_array[index]);
}
for (let index in groups) {
manipulated_text_array.push(groups[index].join("|"));
}
manipulated_index_array = Object.keys(groups).map(x => parseInt(x));
console.log("texts", manipulated_text_array);
console.log("indexes", manipulated_index_array);
Let's say I have two array's
let array1 = ["H","E","", "","O","","","R","L","D"];
let array2 = ["","","L","L","","W","O","","",""];
I want to merge them such that they would then contain:
array3 = ["H","E","L", "L","O","W","O","R","L","D"];
How would I achieve this?
To be more clear I have a target array which is array3 an empty array and then I'm generating random characters and if they match array3 adding them to the blank array in the specific position with react state. It is just not storing the position and character each time but just changing it. SO my idea is to set the state such that I merge the current state with the new characters that are found.
TLDR:- Brute forcing Hello World meme.
You can use Array.prototype.map() to create a new array array3 out of iterating over array1 and get the l (letters) and if any l evaluates to falsey then get the letter at the same i (index) in the array2.
Note that instead of declaring your arrays with let you should always use const because it makes code easier to read within its scope, and const variable always refers to the same object.
Code example:
const array1 = ["H","E","", "","O","","","R","L","D"];
const array2 = ["","","L","L","","W","O","","",""];
const array3 = array1.map((l, i) => l || array2[i]);
console.log(array3);
Try it:
let arr1 = ["H","E","", "","O","","","R","L","D"];
let arr2 = ["","","L","L","","W","O","","",""];
let arr3 = [];
arr1.forEach((val, index) => {
if (val === '') {
arr3[index] = arr2[index];
} else {
arr3[index] = val;
}
});
console.log(arr3);
I create an array with let arr = new Array(99999) but I don't fill it up to arr.length which is 99999, how can I know how much actual, non undefined elements do I have in this array?
Is there a better way than to look for the first undefined?
You could use Array#forEach, which skips sparse elements.
let array = new Array(99999),
count = 0;
array[30] = undefined;
array.forEach(_ => count++);
console.log(count);
The same with Array#reduce
let array = new Array(99999),
count = 0;
array[30] = undefined;
count = array.reduce(c => c + 1, 0);
console.log(count);
For filtering non sparse/dense elements, you could use a callback which returns for every element true.
Maybe this link helps a bit to understand the mechanic of a sparse array: JavaScript: sparse arrays vs. dense arrays.
let array = new Array(99999),
nonsparsed;
array[30] = undefined;
nonsparsed = array.filter(_ => true);
console.log(nonsparsed);
console.log(nonsparsed.length);
The fastest & simplest way to filter items in an array is to... well... use the .filter() function, to filter out only the elements that are valid (non undefined in your case), and then check the .length of the result...
function isValid(value) {
return value != undefined;
}
var arr = [12, undefined, "blabla", ,true, 44];
var filtered = arr.filter(isValid);
console.log(filtered); // [12, "blabla", true, 44]