Fetch unique elements from Array of Array - javascript

I have a Array of String array i want to fetch the unique elements from that array ignoring the case. how can i fetch
Example:
List of array:
[
["java,C,Node,ReactJs"]
["c","Spring"]
["undefined"]
["asdja"]
["Java","Spring"]
["adjasjh"]
["adjasjh"]
["java"]
]
ExpectedList:
[java,C,node,reactjs,spring,..]

Join the array, change to lower case, split by comma, convert into a Set to get the unique words, and then spread back to an array:
const arr = [["java,NO,C,Node,ReactJs"],["c","Spring"],["undefined"],["asdja"],["Java","Spring"],["adjasjh", "Spring-roll"],["adjasjh"],["java", "javascript", "java-script"]];
const result = [...new Set(arr.join().toLowerCase().split(','))];
console.log(result);
Older answer - won't work in all cases:
You can join the array of arrays, and use String.match() with negative lookahead RegExp to get unique strings:
const arr = [["java,NO,C,Node,ReactJs"],["c","Spring"],["undefined"],["asdja"],["Java","Spring"],["adjasjh", "Spring-roll"],["adjasjh"],["java", "javascript", "java-script"]];
const result = arr.join()
.match(/([^,]+\b)(?!.+\1[,|$])/ig);
console.log(result);

You can use reduce and map methods to iterate array and words and also Set to return array of unique elements in the end.
const array = [["java,C,Node,ReactJs"], ["c","Spring"], ["undefined"], ["asdja"], ["Java","Spring"], ["adjasjh"], ["adjasjh"], ["java"] ]
const result = [...new Set(array.reduce((r, e) => {
return r.concat(...e.map(s => s.split(',').map(w => w.toLowerCase())))
}, []))]
console.log(result)

You can flatten your array, convert every value to lowercase, use Set to remove duplicates, and Array.from to convert it back to an array.
If your ["java,C,Node,ReactJs"] is actually: ["java","C","Node","ReactJs"] you can do it this way:
const array = [
["java","C","Node","ReactJs"],
["c","Spring"],
["undefined"],
["asdja"],
["Java","Spring"],
["adjasjh"],
["adjasjh"],
["java"]
];
const unique = Array.from(
new Set([].concat.apply([], array).map(item => item.toLowerCase()))
// ^^^ flatten array
);
console.log(unique);

You could flat the data and use a Map for keeping the first unique value without mutating it.
const flat = (r, a) => Array.isArray(a) ? a.reduce(flat, r) : r.concat(a.split(','));
var data = [["java,C,Node,ReactJs"], ["c", "Spring"], ["undefined"], ["asdja"], ["Java", "Spring"], ["adjasjh"], ["adjasjh"], ["java"]],
unique = Array.from(data
.reduce(flat, [])
.reduce((m, v) => ((l => m.has(l) || m.set(l, v))(v.toLowerCase()), m), new Map)
.values()
);
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Why forEach doesn't working for type changing of item of array

I'm trying to change the type of each element of the array to numeric, but the string iterating over the array and transforming seems to be ignored and the original array remains the same.
arr.forEach(item => Number(item));
This is because you are not assigning it to the source array or not replacing the array with the new one that has all elements of the number type
You can also make it short as
arr.map(Number)
1) Assigining the converted number(from string to number type) back to source array index
const arr = ["1", "2", "5", "7"];
arr.forEach((n, i, src) => (src[i] = Number(n)));
console.log(arr);
2) Assigning a new array that has all elements converted to type number back to arr variable.
let arr = ["1", "2", "5", "7"];
arr = arr.map(n => Number(n));
console.log(arr);
// Foreach does not return anything, so any update you want to save has to be done manually
arr = ['1','200'];
arr.forEach(item => Number(item));
console.log(arr);
// here you are updating the orinal array
arr = ['1','200'];
arr.forEach((item, i ) => arr[i] = Number(item));
console.log(arr);
// here you are creating a new array without impacting the existing array
arr = ['1','200'];
let newArr = arr.map((item) => Number(item));
console.log(arr);
console.log(newArr);
forEach doesn't return anything. It just mutates the array that it's given.
Its callback accepts three arguments. The first is the array element, the second is the index of that element, and the last is the array itself. We only have concern ourselves with the first two in this example.
Because forEach mutates the array you need to assign the the result of coercing the string to a number back to the array index.
const arr = ['1', '2', '3'];
arr.forEach((item, i) => {
arr[i] = Number(item);
});
console.log(arr);
The alternative is to use map which creates a new array. We can use Number directly as the callback because it only accepts one argument which will be the array element.
const arr = ['1', '2', '3'];
const newArr = arr.map(Number);
console.log(newArr);

Convert array of array's each array into array of string

I am trying to convert an array of array's each array into a string.
I know the method flat where all the array of the array becomes a single array but this is not solving my full purpose.
array = [['ba','ab'],['bab','abb']]
my tried code is:
let merged = array.map(a => {
console.log(a)
a.reduce((a, b) => a.concat(b), []);
})
console.log(merged);
Expected output is: [['ba,ab'],['bab, abb']]
You can use Array.prototype.join() for this purpose. From the documentation:
The join() method creates and returns a new string by concatenating all of the elements in an array (or an array-like object), separated by commas or a specified separator string. If the array has only one item, then that item will be returned without using the separator.
Like the following:
const array = [['ba', 'ab'], ['bab', 'abb']];
const result = array.map(e => e.join(','));
console.log(result);
Hope that helps!
You could map the joined values.
var array = [['ba', 'ab'], ['bab', 'abb']],
result = array.map(a => a.join(', '));
console.log(result);
With respect to your comment on #norbitrial answer.
Plus a little JS type conversion hack (just for education, you'd better use join(",")). And I think you should accept his answer.
const array = [['ba', 'ab'], ['bab', 'abb']];
const result = array.map(e => ["" + e]);
console.log(result);

Split an array into small arrays based on text in values

I have big array, which looks like this example:
let array = ['aa-we', 'aa-we__qq', 'aa-we__qw', 'gsPlsOdd', 'bc-po-lp', 'bc-po-lp--ps', 'de', 'de__io', 'de__sl', 'de--xz', 'ccsDdd'];
i want split this array into small arrays by values:
let array = [
['aa-we', 'aa-we__qq', 'aa-we__qw'],
['bc-po-lp', 'bc-po-lp--ps'],
['de', 'de__io', 'de__sl', 'de--xz']
]
// and camelcase strings should be removed
Values in array have syntax like BEM selectors, so if the prefix of different strings is the same, they should be wrapped in a single array.
How can i do this, if possible, without additional libraries?
Thanks for the help or tips!
console.clear()
let data = [
"aa-we",
"aa-we__qq",
"aa-we__qw",
"gsPlsOdd",
"bc-po-lp",
"bc-po-lp--ps",
"de",
"de__io",
"de__sl",
"de--xz",
"ccsDdd",
];
resultO = data.reduce((acc, val, idx) => {
if (val.match(/[A-Z]/)) {return acc;}
const sel = val.replace(/^(.*)(__|--).*$/g, "$1");
acc[sel] = acc[sel] || [];
acc[sel].push(val)
return acc;
}, {})
resultA = Object.values(resultO)
console.log(resultA)
I'd do something like this and then filter out what you don't want.
let array = ['aa-we', 'aa-we__qq', 'aa-we__qw', 'gsPlsOdd', 'bc-po-lp', 'bc-po-lp--ps', 'de', 'de__io', 'de__sl', 'de--xz', 'ccsDdd'];
array = array.filter((a) => !a.match(/[A-Z]/))
let result = groupBy(array, (str)=> str.split(/[-_]/)[0])
console.log(Object.values(result))
function groupBy(arr, condition) {
return arr.reduce((result, current) => {
const key = condition(current);
(result[key] || (result[key] = [])).push(current)
return result
}, {})
}
The algorithm can be as follows:
Create Map<Prefix,ValuesArray>
For each element in array:
Get it's prefix, e.g. "ab", skip element if invalid (e.g. no prefix exist or camel case)
Add to corresponding hashed bucket
Join values from Map into one array
JS has all the primitives to implement this, just take a look at Map/Object for hashing and Array (map/filter/reduce) for processing.

JavaScript find "newest" version of a string

This is probably something really easy, but I can't think of any good solution here:
I have an array of strings:
let array = ['House1', 'House2', 'House3', 'Block1', 'Block2', 'BlockSpecial1'];
In time this array will change, but at any point I want to able to reduce that array to just the "newest" versions of the strings (based on the ending numbers, they may become 2- or 3-digit at some point), so what I want in the end would be:
['House3', 'Block2', 'BlockSpecial1']
Reduce the array to an object with the string as key, and the version as value. To get the string and version, you can use String.match(), and array destructuring. Then use Object.entries(), and Array.map() to combine it back to strings:
const array = ['House1', 'House2', 'House3', 'Block1', 'Block2', 'BlockSpecial1'];
const result = Object.entries(array.reduce((r, s) => {
const [, str, version] = s.match(/([A-Za-z]+)(\d+)/);
r[str] = (r[str] || 0) > version ? r[str] : version; // or r[str] = version if the versions are always in the right order
return r;
}, Object.create(null)))
.map(([k, v]) => k + v);
console.log(result);
You can do this actually very cleanly by creating a Map.
const array = ['House1', 'House2', 'House3', 'Block1', 'Block2', 'BlockSpecial1'];
const re = /^([^]+?)(\d+)$/;
const result = [...new Map(array.map(s => re.exec(s).slice(1)))]
.map(a => a.join(""));
console.log(result);
Here's the rundown...
In a .map() over the original array, divide each string between its text and number using a regex, and return an array that has only the captured parts.
Have the .map() result become the argument to the Map constructor. This creates the map with each first member of the sub array as each key, and the second as the value.
Because a Map must have unique keys, you only get the last key produced for each redundant key, which will also have the highest number.
Then convert that map to its remaining key/value entries, and join them back into a string.
Here's the same code from above, but breaking it into parts so that we can log each step.
const array = ['House1', 'House2', 'House3', 'Block1', 'Block2', 'BlockSpecial1'];
const re = /^([^]+?)(\d+)$/;
const keysVals = array.map(s => re.exec(s).slice(1));
console.log("original split:", keysVals);
const m = new Map(keysVals);
const mapKeysVals = [...m];
console.log("mapped keys vals", mapKeysVals);
const result = mapKeysVals.map(a => a.join(""));
console.log("result", result);
let tmp, name;
let array = ['House1', 'House2', 'House3', 'Block1', 'Block2', 'BlockSpecial1'];
let newest = array.sort((a, b) => b.match(/\d+$/)[0] - a.match(/\d+$/)[0]).sort().reverse()
.reduce((newArr, item) => (name = item.match(/.+[^\d]+/)[0], name != tmp && (newArr.push(item), tmp = name), newArr), []);
console.log(newest) //[ 'House3', 'BlockSpecial1', 'Block2' ]

Removing a specific element from each array in a 2D array

I am trying to remove the 3rd element from each array with the array.
What I have:
data =
[["51.9435","-4.26697","450","125"],
["51.9437","-4.26717","450","125"],
["51.9438","-4.26733","450","125"],
["51.944","-4.26748","450","125"]]
What I need:
data =
[["51.9435","-4.26697","125"],
["51.9437","-4.26717","125"],
["51.9438","-4.26733","125"],
["51.944","-4.26748","125"]]
I have assumed using splice but can not think how I would use it with a 2d array.
Use splice on each subarray.
const data = [["51.9435","-4.26697","450","125"],
["51.9437","-4.26717","450","125"],
["51.9438","-4.26733","450","125"],
["51.944","-4.26748","450","125"]]
for( const array of data )
array.splice(2, 1)
console.log(data)
Edit: to keep the original data intact, you'd need to copy the arrays prior to splicing.
const data = [["51.9435","-4.26697","450","125"],
["51.9437","-4.26717","450","125"],
["51.9438","-4.26733","450","125"],
["51.944","-4.26748","450","125"]]
const converted = data.map(function(array){
const copy = array.slice()
copy.splice(2, 1)
return copy
})
console.log(data)
console.log(converted)
You can use the following code snippet
data =[["51.9435","-4.26697","450","125"],
["51.9437","-4.26717","450","125"],
["51.9438","-4.26733","450","125"],
["51.944","-4.26748","450","125"]];
data.map( (arr) => {arr.splice(2,1);});
console.log(data);
You can use .map() with .splice().
.map() creates a new array with values returning from callback function.
.splice() removes one or more elements from the array.
Demo:
let data =[
["51.9435","-4.26697","450","125"],
["51.9437","-4.26717","450","125"],
["51.9438","-4.26733","450","125"],
["51.944","-4.26748","450","125"]
];
let removeIndex = (array, index) => array.map(a => (a.splice(index, 1), a));
console.log(removeIndex(data, 2));
Docs:
Array.prototype.map()
Array.prototype.splice()
Arrow Functions
you can use splice supplying the index of the index you want to remove in this case 2 and 1 if you want to remove only one element.
data = [
["51.9435", "-4.26697", "450", "125"],
["51.9437", "-4.26717", "450", "125"],
["51.9438", "-4.26733", "450", "125"],
["51.944", "-4.26748", "450", "125"],
]
data.forEach( arr => {
// loop over all arrays to get the individual ones.
arr.splice(2 , 1) // then call splice.
})
console.log(data)

Categories

Resources