How create two dimensional (2D) string array dynamic in JavaScript - javascript

If the word is ABC
A[0][0]="AA" A[0][1]="AB" A[0][2]="AC"
A[1][0]="BA" A[1][1]="BB" A[1][2]="BC"
A[2][0]="CA" A[2][1]="CB" A[2][2]="CC"
using for, string or array method.

const a = [..."ABC"];
console.log(
a.map(l => a.map(c => l + c))
);

An odd request. Is this what you are looking for?
const word = "ABC";
const letters = word.split("");
const array = [];
letters.forEach((letter1,index1) => {
letters.forEach((letter2,index2) => {
if (!array[index1]) {
array[index1] = [];
}
array[index1][index2] = letter1+letter2;
});
});
console.log(array);
UPDATE:
Another version using older Javascript. Also, check out Asaf's solution using a more functional approach below, is very elegant.
var word = "ABC";
var letters = word.split("");
var array = [];
for(var index1 = 0;index1!==letters.length;index1++) {
for(var index2 = 0;index2!==letters.length;index2++) {
if (!array[index1]) {
array[index1] = [];
}
array[index1][index2] = letters[index1]+letters[index2];
}
}
console.log(array);

Related

I have a array of string have to find all the common character present from all strings

I have a array of string.
let arr=["robin","rohit","roy"];
Need to find all the common character present in all the strings in array.
Output Eg: r,o
I have tried to create a function for above case with multiple loops but i want to know what should be the efficient way to achive it.
Here's a functional solution which will work with an array of any iterable value (not just strings), and uses object identity comparison for value equality:
function findCommon (iterA, iterB) {
const common = new Set();
const uniqueB = new Set(iterB);
for (const value of iterA) if (uniqueB.has(value)) common.add(value);
return common;
}
function findAllCommon (arrayOfIter) {
if (arrayOfIter.length === 0) return [];
let common = new Set(arrayOfIter[0]);
for (let i = 1; i < arrayOfIter.length; i += 1) {
common = findCommon(common, arrayOfIter[i]);
}
return [...common];
}
const arr = ['robin', 'rohit', 'roy'];
const result = findAllCommon(arr);
console.log(result);
const arr = ["roooooobin","rohit","roy"];
const commonChars = (arr) => {
const charsCount = arr.reduce((sum, word) => {
const wordChars = word.split('').reduce((ws, c) => {
ws[c] = 1;
return ws;
}, {});
Object.keys(wordChars).forEach((c) => {
sum[c] = (sum[c] || 0) + 1;
});
return sum;
}, {});
return Object.keys(charsCount).filter(key => charsCount[key] === arr.length);
}
console.log(commonChars(arr));
Okay, the idea is to count the amount of times each letter occurs but only counting 1 letter per string
let arr=["robin","rohit","roy"];
function commonLetter(array){
var count={} //object used for counting letters total
for(let i=0;i<array.length;i++){
//looping through the array
const cache={} //same letters only counted once here
for(let j=0;j<array[i].length;j++){
//looping through the string
let letter=array[i][j]
if(cache[letter]!==true){
//if letter not yet counted in this string
cache[letter]=true //well now it is counted in this string
count[letter]=(count[letter]||0)+1
//I don't say count[letter]++ because count[letter] may not be defined yet, hence (count[letter]||0)
}
}
}
return Object.keys(count)
.filter(letter=>count[letter]===array.length)
.join(',')
}
//usage
console.log(commonLetter(arr))
No matter which way you choose, you will still need to count all characters, you cannot get around O(n*2) as far as I know.
arr=["robin","rohit","roy"];
let commonChars = sumCommonCharacters(arr);
function sumCommonCharacters(arr) {
data = {};
for(let i = 0; i < arr.length; i++) {
for(let char in arr[i]) {
let key = arr[i][char];
data[key] = (data[key] != null) ? data[key]+1 : 1;
}
}
return data;
}
console.log(commonChars);
Here is a 1 liner if anyone interested
new Set(arr.map(d => [...d]).flat(Infinity).reduce((ac,d) => {(new RegExp(`(?:.*${d}.*){${arr.length}}`)).test(arr) && ac.push(d); return ac},[])) //{r,o}
You can use an object to check for the occurrences of each character. loop on the words in the array, then loop on the chars of each word.
let arr = ["robin","rohit","roy"];
const restWords = arr.slice(1);
const result = arr[0].split('').filter(char =>
restWords.every(word => word.includes(char)))
const uniqueChars = Array.from(new Set(result));
console.log(uniqueChars);

How do I convert a string to a dictionary in javascript?

I have a string
var str = "1:6,5,2,2:3";
I want to convert this str into a js dictionary such that:
var dict = {1:"6,5,2",
2:"3"};
so that I can fetch the values by their respective key index. How do I convert it?
I had tried this code to store the splitted values into an array:
var pages = "1:6,5,2,2:3";
var numbers = [];
if (pages.includes(',')) {
page_nos = pages.split(',');
for (var i = 0; i < page_nos.length; i++) {
if (page_nos[i].includes(':')) {
var n = page_nos[i].split(':');
numbers.push(n[1]);
} else {
numbers.push(page_nos[i]);
}
}
} else {
page_nos = pages.split(':');
numbers.push(page_nos[1])
};
console.log('numbers: ', numbers);
But it's incorrect, as without dictionary it's impossible to know what value belongs to which index
If you cannot make your input string a proper JSON or another easily parsable format in the first place, this answers your question:
const str = "1:6,5,2,2:3";
const obj = str.split(/,(?=\d+:)/).reduce((accu, part) => {
const [k, v] = part.split(':', 2);
accu[k] = v;
return accu;
}, {});
console.log(obj);
Cut the string at all commas that are followed by digits and a colon. Each part has a key in front of a colon and a value after it, which should be stuffed in an object in this format.
No mutations solution.
const str = "1:6,5,2,2:3";
const dict = str
.split(/(\d+:.*)(?=\d+:)/g)
.reduce((t, c) => {
const [key, value] = c.replace(/,$/, "").split(/:/);
return { ...t, [key]: value }
});
console.log(dict);
if you consider not using regular expression, you might try this as well.
to take out a dict (Object) from that string, this will do.
var pages = "1:6,5,2,2:3";
function stringToObject(str) {
var page_object = {};
var last_object;
str.split(",").forEach((item) => {
if (item.includes(":")) {
page_object[item.split(":")[0]] = item.split(":")[1];
last_object = item.split(":")[0];
} else {
page_object[last_object] += `,${item}`;
}
});
return page_object;
}
console.log(stringToObject(pages))
Presented below may be one possible solution to achieve the desired objective.
NOTE:
In lieu of var the code uses either let or const as applicable.
Code Snippet
const pages = "1:6,5,2,2:3";
const resObj = {};
let page_nos, k;
if (pages.includes(',')) {
page_nos = pages.split(',');
for (let i = 0; i < page_nos.length; i++) {
if (page_nos[i].includes(':')) {
let n = page_nos[i].split(':');
k = n[0];
resObj[k] = n[1].toString();
} else {
resObj[k] += ", " + page_nos[i].toString();
}
}
} else {
page_nos = pages.split(':');
resObj[page_nos[0]] = [page_nos[1]]
numbers.push(page_nos[1])
};
console.log('result object: ', resObj);
This code essentially fixes the code given in the question. It is self-explanatory and any specific information required may be added based on questions in comments.
You could take nested splitring for entries and get an object from it.
const
str = "1:6,5,2,2:3",
result = Object.fromEntries(str
.split(/,(?=[^,]*:)/)
.map(s => s.split(':'))
);
console.log(result);

texts in array converts to objects

I am using node to convert an array to object, I have an array looks like this
[
'items[0].book=Book1',
'items[0].color=Red',
'items[0].bookCode=#1',
'items[1].book=Book2',
'items[1].color=Yellow',
'items[1].bookCode=#2',
'items[2].book=Book3',
'items[2].color=Blue',
'items[2].bookCode=#3',
...
]
I am trying to convert it to be objets in one array
items:[
{
book: "Book1",
color: "Red",
bookCode: "#1"
},
{
book: "Book2",
color: "Yellow",
bookCode: "#2"
},
...
]
I found it is easy to conver it uses a 3rd party lib like setKeypath/set,
const obj = {};
const arr = [items......(like above)]
arr.forEach((val => {
if (val.startsWith('items[')) {
const splitWord = item.split('=');
setKeypath(obj, splitWord[0], splitWord[1]);
}
});
I am seeking a way if it can be done the same output with es6, so I don't really need a library. Thanks
const items = [
"items[0].book=Book1",
"items[0].color=Red",
"items[0].bookCode=#1",
"items[1].book=Book2",
"items[1].color=Yellow",
"items[1].bookCode=#2",
"items[2].book=Book3",
"items[2].color=Blue",
"items[2].bookCode=#3"
];
let res = [];
let currId = "";
let currItem = null;
for (let i = 0; i < items.length; i++) {
let parts = items[i].split(".");
if (currId!==parts[0] && currItem) { //new item
res.push(currItem)
currId = parts[0];
}
if (!currItem)
currItem = {};
let keyValue = parts[1].split("=");
currItem[keyValue[0]] = keyValue[1]
}
console.log({items: res})
You may first find all values by regex, and insert the attribute to each corresponding element one by one. This approach works for whatever ordering the array is, and whatever attributes there are, as long as each element follow the same pattern.
let items = [
"items[1].bookCode=#2",
"items[0].book=Book1",
"items[0].bookCode=#1",
"items[1].book=Book2",
"items[2].bookCode=#3",
"items[1].color=Yellow",
"items[2].book=Book3",
"items[2].color=Blue",
"items[0].color=Red",
"items[4].test=test!"
];
let indexPattern = /\[(\d*)\]/;
let attrPattern = /\.(.*)=/;
let valuePattern = /=(.*)/;
let obj = Object.values(
items.reduce((obj, element) => {
let index = element.match(indexPattern)[1];
let attr = element.match(attrPattern)[1];
let value = element.match(valuePattern)[1];
if (!obj.hasOwnProperty(index)) obj[index] = {};
obj[index][attr] = value;
return obj;
}, {})
);
console.log(obj);
[
'items[0].book=Book1',
'items[0].color=Red',
'items[0].bookCode=#1',
'items[1].book=Book2',
'items[1].color=Yellow',
'items[1].bookCode=#2',
'items[2].book=Book3',
'items[2].color=Blue',
'items[2].bookCode=#3',
].reduce((acc, str) => {
const index = Number(str.slice(str.indexOf('[') + 1, str.indexOf(']')));
if (!acc[index]) {
acc[index] = {};
}
const entry = [str.slice(str.indexOf('.') + 1, str.indexOf('=')), str.slice(str.indexOf('=') + 1)];
acc[index][entry[0]] = entry[1];
return acc;
}, []);
Here I pick apart the string you're given based on the consistent format, grab the index, key, and value, and then just use Array#reduce to do the work of putting the array together.
Documentation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
I think a smattering of regex would do the trick:
const ar = [
'items[0].book=Book1',
'items[0].color=Red',
'items[0].bookCode=#1',
'items[1].book=Book2',
'items[1].color=Yellow',
'items[1].bookCode=#2',
'items[2].book=Book3',
'items[2].color=Blue',
'items[2].bookCode=#3'
]
const result = [];
ar.forEach(item => {
const index = parseInt(item.match(/\[([0-9]+)\]/)[1]);
const params = item.split(".")[1].split("=");
if(!result[index])
result[index] = {}
result[index][params[0]] = params[1];
})
console.log(result)
Note that item.match(/\[([0-9]+)\]/) matches the number inside your brackets. match returns an array where 1 is the index of the actual value between the brackets.

Find common words and push into new array

I have Array below and attached output.
`var
arrayData=['cat','mat','tac','hiller','mamaer','llerih','eramam'];
output : [[cat,tac], [mat], [hiller,llerih], [mamaer,erama]];`
Want to extract common letter in an array and store in new array.
i was trying to implement using array.reducer.
You can do this with Map and a simple loop. The idea is you record each word by creating a "key" from the sum of their character code and length of the word.
Used Array#Reduce to sum the words character codes.
i.e.:
//sum of each letter's character code using reduce
const res1 = "test".split("").reduce((a,c)=>a+c.charCodeAt(), 0);
const res2 = "ttes".split("").reduce((a,c)=>a+c.charCodeAt(), 0);
const l = "test".length;
const key1 = `${l}_${res1}`;
const key2 = `${l}_${res2}`;
console.log(key1, key2, key1 === key2); //4_448 4_448 true
i.e. (without reduce and with for loop):
function sum(word){
let s = 0;
for(let i = 0; i < word.length; i++){
s += word[i].charCodeAt();
}
return s
}
//sum of each letter's character code using reduce
const res1 = sum("test");
const res2 = sum("ttes");
const l = "test".length;
const key1 = `${l}_${res1}`;
const key2 = `${l}_${res2}`;
console.log(key1, key2, key1 === key2); //4_448 4_448 true
Recording the length of the word adds an extra level of security incase two different words of lengths different had the same sum
Full Solution:
const data = ['cat','mat','tac','hiller','mamaer','llerih','eramam'];
const m = new Map();
for(let i = 0; i < data.length; i++){
const word = data[i];
const sum = word.split("").reduce((a,c)=>a+c.charCodeAt(), 0);
const key = `${word.length}_${sum}`;
m.set(key, [word].concat(m.get(key)||[]));
}
const res = Array.from(m.values());
console.log(res);
I solved it with a different way, I sorted them, grouped them then displayed them by index.
var arrayData=['cat','mat','tac','hiller','mamaer','llerih','eramam'];
var sortedArrayData = arrayData.map(itm => itm.split('').sort((a,b) => a>b).join(''));
var data = {};
sortedArrayData.forEach((itm, indx) => {
if(!data[itm]) data[itm] = [];
data[itm].push(indx)
});
var result = Object.keys(data).map(key => {
return data[key].map(it => arrayData[it])
})
console.log(result)
try it here

Why is this returning an empty string?

I would like this to return s1 and s1 combined together, only the unique characters sorted in a new string called sortedString. Instead I get an empty string output.
ex input and output:
a = "xyaabbbccccdefww"
b = "xxxxyyyyabklmopq"
longest(a, b) -> "abcdefklmopqwxy"
function longest(s1, s2) {
var sortedString = '';
var a = s1.split();
var b = s2.split();
for (i=0; i < a.length; i++) {
if (!sortedString.includes(a[i])) {
sortedString.concat(a[i]);
}
}
for (j=0; j < b.length; j++) {
if (!sortedString.includes(b[j])) {
sortedString.concat(b[j]);
}
}
return sortedString.sort();
}
In javascript String type is immutable and concat method don't mutate input so when you type:
sortedString.concat(b[j]);
sortedString is never muted. You should make this instead :
sortedString = sortedString.concat(b[j]);
You need to pass an empty string to split if you want to separate the string into a list of characters.
However, I would strongly recommend you solve this declaratively:
const allChars = s1.split('').concat(s2.split(''));
return allChars
.filter((char) => allChars.indexOf(char) === allChars.lastIndexOf(char))
.sort()
.join('');
var a = "xyaabbbccccdefww";
var b = "xxxxyyyyabklmopq";
var mySet = new Set(a.split("").concat(b.split("")));
var result = Array.from(mySet).sort().join("");
console.log(result);
With ES6, you could use Set with spread syntax ... for splitting the string and for populating an array.
var a = "xyaabbbccccdefww",
b = "xxxxyyyyabklmopq",
result = [...new Set([...(a + b)])].sort().join("");
console.log(result);

Categories