JavaScript find "newest" version of a string - javascript

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' ]

Related

how to convert array of object to comma separated array of object

I have array of object and I want to convert this to comma separated object.
let arr = [{name:"k"},{name:"p"}];
console.log(...arr.join(','));
I'm getting this [ o b j e c t O b j e c t ] , [ o b j e c t O b j e c t ]
I want to in this format {name:"k"},{name:"p"}.
The default conversion of plain objects to strings results in "[object Object]". (More about why you got the specific output you got below.) If you want something different, you have to do that with your own code.
For instance, you could use map to convert the objects to strings, then use join on the result:
const result = arr.map(({name}) => `{name: ${JSON.stringify(name)}`).join(",");
Live Example:
let arr = [{name:"k"},{name:"p"}];
const result = arr.map(({name}) => `{name: ${JSON.stringify(name)}}`).join(",");
console.log(result);
That just does the one specific property of course. If you want to include others, you'll need a loop/mapping operation in the map callback (perhaps starting with Object.entries on the object).
const result = arr.map(obj => {
const props = Object.entries(obj).map(([name, value]) => `${name}: ${JSON.stringify(value)}`);
return `{${props}}`;
}).join(",");
Live Example:
let arr = [{name:"k"},{name:"p"}];
const result = arr.map(obj => {
const props = Object.entries(obj).map(([name, value]) => `${name}: ${JSON.stringify(value)}`);
return `{${props}}`;
}).join(",");
console.log(result);
If you don't mind quotes around the property names, then as shobe said you can do that by applying JSON.stringify to the entire object.
const result = arr.map(obj => JSON.stringify(obj)).join(",");
But your question didn't show quotes around property names.
Live Example:
let arr = [{name:"k"},{name:"p"}];
const result = arr.map(obj => JSON.stringify(obj)).join(",");
console.log(result);
Why you got the specific result you got:
I was initially surprised by the output you got, but it does make sense after a moment's thought: Your code does console.log(...arr.join(",")), which does this:
Calls join on arr, which combines its entries together into a string using their default convert-to-string behavior, with a single comma in-between.
Spreads out that string into discrete arguments to console.log as though you'd written console.log("[", "o", "j" etc.
Why not! just turn it to JSON format, then remove open or closed square-brackets:
let arr = [{name:"k"},{name:"p"}];
console.log(JSON.stringify(arr).replace(/\[|\]/g,''))
Result as expected: {"name":"k"},{"name":"p"}

How to create javascript object from concatenated key value pairs

I need to create an object from a variable created with concateneated key value pairs.
HardCoded (it is an array as dataSource for a jquery datatable), it looks like this:
obj = {
totalValue: valVar,
totalReceiptValue: receiptVar
}
dataSourceArray.push(obj);
My variable is:
cumulator ="totalValue:8573.0000,totalReceiptValue:3573.00,"
I've tried this,
var obj = {};
const name = "";
const value = cumulator;
obj[name] = value;
dataSourceArray.push(obj);
but then I have an extra key i.e. "": in the object which of course fails for my requirements.
How do I do this?
Thanks
Assuming that there are no extra : or , signs that could mess with the logic, it can be achieved simply by spliting the strings and using the built in method Object.prototype.fromEntries
const input = "totalValue:8573.0000,totalReceiptValue:3573.00,";
const output = Object.fromEntries( // combine entries into object
input.split(",") // divide into pairs
.filter(Boolean) // remove empty elements (comma at the end)
.map((el) => el.split(":")) // divide the pair into key and value
)
console.log(output)
There apparently being some problems with IE and Edge, the code above can be fixed by writing own implementation of from Entries and opting to not use arrow functions.
const input = "totalValue:8573.0000,totalReceiptValue:3573.00,";
const entries = input.split(",") // divide into pairs
const output = {};
for (let i=0; i<entries.length; i++) {
if (!entries[i]) continue; // remove empty elements (comma at the end)
const [key, val] = entries[i].split(":"); // divide the pair into key and value
output[key]=val; // combine entries into object
}
console.log(output)
You can simply use split, map reduce functions.
Try this.
const input = "totalValue:8573.0000,totalReceiptValue:3573.00,";
const result = input.split(',').filter(Boolean).map(function(text) {
return text.split(':')
}).reduce(function(acc, curr) {
acc[curr[0]] = curr[1]
return acc
}, {})
console.log(result)

Sort array elements on JavaScript

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);

Alphabetically sort array with no duplicates

I'm trying to create a function that takes an array of strings and returns a single string consisting of the individual characters of all the argument strings, in alphabetic order, with no repeats.
var join = ["test"];
var splt = (("sxhdj").split(""))
var sort = splt.sort()
var jn = sort.join("")
join.push(jn)
function removeDuplicates(join) {
let newArr = {};
join.forEach(function(x) { //forEach will call a function once for
if (!newArr[x]) {
newArr[x] = true;
}
});
return Object.keys(newArr);
}
console.log(removeDuplicates(join));
I can not get the current code to work
Check out the comments for the explanation.
Links of interest:
MDN Array.prototype.sort.
MDN Set
var splt = ("sxhdjxxddff").split("")
// You need to use localeCompare to properly
// sort alphabetically in javascript, because
// the sort function actually sorts by UTF-16 codes
// which isn't necessarily always alphabetical
var sort = splt.sort((a, b)=>a.localeCompare(b))
// This is an easy way to remove duplicates
// by converting to set which can't have dupes
// then converting back to array
sort = [...new Set(sort)]
var jn = sort.join("");
console.log(jn);
Something like this :) Hope it helps!
const string = 'aabbccd';
const array = string.split('');
let sanitizedArray = [];
array.forEach(char => {
// Simple conditional to check if the sanitized array already
// contains the character, and pushes the character if the conditional
// returns false
!sanitizedArray.includes(char) && sanitizedArray.push(char)
})
let result = sanitizedArray.join('')
console.log(result);
Try this:
const data = ['ahmed', 'ghoul', 'javscript'];
const result = [...data.join('')]
.filter((ele, i, arr) => arr.lastIndexOf(ele) === i)
.sort()
.join('');
console.log(result)
There are probably better ways to do it, one way is to map it to an object, use the keys of the object for the used letters, and than sorting those keys.
const words = ['foo', 'bar', 'funky'];
const sorted =
Object.keys(
([...words.join('')]) // combine to an array of letters
.reduce((obj, v) => obj[v] = 1 && obj, {}) // loop over and build hash of used letters
).sort() //sort the keys
console.log(sorted.join(''))

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.

Categories

Resources