Related
I have a metric/multi dimension array like below
[
[a,b,c,d],
[d,a,c,b],
[a,d,b,a],
[c,c,d,a]
]
I am required to update my given metric and keep track of change in a such a way
An element can repeat itself in one column only.
An element can not occur in other columns if it has occurred in a column.
If the above condition occur update the element by appending the column index to all its occurrence in a column.
In the above example element at index [1][1]('a' in row 2 and column 2) has occur in column 1. It and all its occurrence should update to 'a1'. Similarly 'd' and 'c' should update to 'd1' and 'c1' respectively.
In the next column Column 3, 'c', 'b', 'd' in column 3 should update to 'c2','b2','d2' because 'b' has occurred is column 2, similarly 'c' and 'd' has occurred before.
In next column Column 4 'd','b','a' will update to 'd4','b4','a4'.
Resulted metric will look like
[
[a,b, c3,d4],
[d,a2,c3,b4],
[a,d2,b3,a4],
[c,c2,d3,a4]
]
Keep track part
we can keep track like
var dictionary = [{"updatedValue":"originalValue"},...]
var dictionary = [{"a2":"a"},{"d2","d"},{"c2","c"},{"c3":"c"},{"b3":"b"},{"d3":"d"},{"d4","d"},{"a4":"a"},{"b4","b"}];
so far I have tried this
var flatData = [
['a', 'b', 'c', 'd'],
['d', 'a', 'c', 'b'],
['a', 'd', 'b', 'a'],
['c', 'c', 'd', 'a'],
];
for (var i = 0; i < flatData.length; i++) {
for (var j = 0; j < flatData[i].length; j++) {
var element = flatData[i][j];
for (var k = 0; k < flatData.length; k++) {
for (var l = 0; l < flatData[k].length; l++) {
if (j != l) {
if (element == flatData[k][l]) {
flatData[k][l] = flatData[k][l] + l;
}
}
}
}
}
}
console.log(JSON.stringify(flatData));
Solution uses a Map(could be plain object also) where first time a value is encountered a new entry is created that has an object {col: firstColIndexFound, count:0}.
Next time same value is encountered it checks stored column index and if different updates the count and creates a new value
const data = [
['a', 'b', 'c', 'd'],
['d', 'a', 'c', 'b'],
['a', 'd', 'b', 'a'],
['c', 'c', 'd', 'a']
];
const dict = {};
const map = new Map();
for (let c = 0; c < data[0].length; c++) { // c for colIndex
for (let r = 0; r < data.length; r++) { // r for rowIndex
const el = data[r][c];
if (!map.has(el)) {
// first time found create new entry
map.set(el, {col: c, count: 0});
}
const entry = map.get(el);
// if column index different than first column found update value
if (c !== entry.col) {
entry.count++;
const nVal = el + entry.count;
dict[nVal] = el;
data[r][c] = nVal;
}
}
}
console.log(JSON.stringify(data))
console.log(dict)
.as-console-wrapper {
max-height: 100%!important;
top: 0;
}
I am trying to push 3 random items from an array into a new array. I use splice() to grab an item and remove it from the old array. When I push() the items, I would like to get them back in a single array.
For example:
["b", "f", "a"]
This is my code:
const letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
let newletters = [];
for (let i = 0; i < 3; i++) {
newletters.push(letters.splice(Math.floor(Math.random() * letters.length), 1));
}
console.log(newletters);
It seems like I am pushing the spliced items as arrays into the new array, is there a way to fix this?
[
[
"b"
],
[
"f"
],
[
"a"
]
]
You could spread ... the array from Array#splice.
Or take the first element with and index.
letters.splice(Math.floor(Math.random() * letters.length)[0]
const letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
let newletters = [];
for (let i = 0; i < 3; i++) {
newletters.push(...letters.splice(Math.floor(Math.random() * letters.length), 1));
}
console.log(newletters);
You can use the function Array.prototype.concat instead.
const letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
let newletters = [];
for (let i = 0; i < 3; i++) {
newletters = newletters.concat(letters.splice(Math.floor(Math.random() * letters.length), 1));
}
console.log(newletters);
Use the ... operator inside the push statement.
const letters = ['a', 'b', 'c', 'd', 'e'];
const newLetters = []
newLetters.push(...letters.splice(1, 2)) // Equal to newLetters.push('b', 'c')
console.log(newletters)
const letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
let newletters = [];
for (let i = 0; i < 3; i++) {
newletters.push(letters.splice(Math.floor(Math.random() * letters.length), 1));
}
console.log(newletters.flat());
I am trying to loop through nested arrays and reorder them into new nested arrays. For example, take [[a,b,c,d], [e,f,g,h], [i,j,k,l]] and change it into [[a,e,i], [b,f,j], [c,g,k], [d,h,l]]
let rowArr = [[a,b,c,d], [e,f,g,h], [i,j,k,l]];
let newRowArr = [];
let length = rowArr.length;
for(let i = 0; i<length; i++){
for(let j = 0; j<rowArr.length; j++){
newRowArr.push(rowArr[i][j]);
j+=rowArr.length;
}
console.log(newRowArr) //I get only [a,e,i]
I am missing something obvious but why won't it loop the additional times to push the other letters into the array?
You could just use the nested loop where i and j are names for outer in inner index names and then use them to add to new array as result[j][i] = current inner loop value
let arr = [
['a', 'b', 'c', 'd'],
['e', 'f', 'g', 'h'],
['i', 'j', 'k', 'l']
];
const result = []
arr.forEach((a, i) => {
a.forEach((e, j) => {
if (!result[j]) result[j] = []
result[j][i] = e
})
})
console.log(result)
You can use Array.prototype.map:
let rowArr = [['a', 'b', 'c', 'd'], ['e', 'f', 'g', 'h'], ['i', 'j', 'k', 'l']];
let newRowArr = [];
let arraySize = 4;
const arrayColumn = (arr, n) => arr.map(x => x[n]);
for (let i = 0; i < arraySize; i++) {
newRowArr.push(arrayColumn(rowArr, i));
}
console.log(newRowArr);
I have an array of objects
const objects = [a, b, c, d, e, f, g ... ]
and I want them to turn into
const result = [a, [b, c], d, [e, f], g ... ]
Any ideas?
[Edit] My apologies. This is my first post, didn't know I have to show my attempts. I don't think I deserve the mean comments either, be nice people. I solved it after a head-banging 4 hours. Here is my solution:
const result = []
const method = array => {
for (let i = 0; i < array.length; i += 3) {
const set = new Set([array[i + 1], array[i + 2]])
if (i !== array.length - 1) {
result.push(array[i])
result.push(Array.from(set))
} else {
result.push(array[i])
}
}
}
Thanks for the responses guys! I read every single one of them.
You could take a while loop and push either an item or a pair of items.
var array = ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
grouped = [],
i = 0;
while (i < array.length) {
grouped.push(array[i++]);
if (i >= array.length) break;
grouped.push(array.slice(i, i += 2));
}
console.log(grouped);
You can do this with plain for loop and % modulo operator.
const objects = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
const result = []
for(let i = 0; i < objects.length; i++) {
if(i % 3 === 0) {
const arr = objects.slice(i + 1, i + 3)
result.push(objects[i])
if(arr.length) result.push(arr)
}
}
console.log(result)
this is my solution:
const objects = ["a", "b", "c", "d", "e", "f", "g"];
let result = [];
let toGroup = false;
for(let i = 0; i < objects.length ; i++){
if(toGroup){
result.push([objects[i], objects[++i]]);
}
else result.push(objects[i]);
toGroup = !toGroup;
}
this has a particular case that you have not specified, where it doesn't work, for example if inside objects there are 2 elements, and so i don't know what you would like to do in that case
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
var point = 'c';
How can I split the "arr" into two arrays based on the "point" variable, like:
['a', 'b']
and
['d', 'e', 'f']
var arr2 = ['a', 'b', 'c', 'd', 'e', 'f'];
arr = arr2.splice(0, arr2.indexOf('c'));
To remove 'c' from arr2:
arr2.splice(0,1);
arr contains the first two elements and arr2 contains the last three.
This makes some assumptions (like arr2 will always contain the 'point' at first assignment), so add some correctness checking for border cases as necessary.
Use indexOf and slice
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
var indexToSplit = arr.indexOf('c');
var first = arr.slice(0, indexToSplit);
var second = arr.slice(indexToSplit + 1);
console.log({first, second});
Sharing this convenience function that I ended up making after visiting this page.
function chunkArray(arr,n){
var chunkLength = Math.max(arr.length/n ,1);
var chunks = [];
for (var i = 0; i < n; i++) {
if(chunkLength*(i+1)<=arr.length)chunks.push(arr.slice(chunkLength*i, chunkLength*(i+1)));
}
return chunks;
}
Sample usage:
chunkArray([1,2,3,4,5,6],2);
//returns [[1,2,3],[4,5,6]]
chunkArray([1,2,3,4,5,6,7],2);
//returns [[1,2,3],[4,5,6,7]]
chunkArray([1,2,3,4,5,6],3);
//returns [[1,2],[3,4],[5,6]]
chunkArray([1,2,3,4,5,6,7,8],3);
//returns [[1,2],[3,4,5],[6,7,8]]
chunkArray([1,2,3,4,5,6,7,8],42);//over chunk
//returns [[1],[2],[3],[4],[5],[6],[7],[8]]
Try this one:
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
var point = 'c';
var idx = arr.indexOf(point);
arr.slice(0, idx) // ["a", "b"]
arr.slice(idx + 1) // ["d", "e", "f"]
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
var point = 'c';
Array.prototype.exists = function(search){
for (var i=0; i<this.length; i++) {
if (this[i] == search) return i;
}
return false;
}
if(i=arr.exists(point))
{
var neewArr=arr.splice(i);
neewArr.shift(0);
console.log(arr); // output: ["a", "b"]
console.log(neewArr); // output: ["d", "e", "f"]
}
Here is an example.
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
var point = 'c';
var i = arr.indexOf(point);
var firstHalf, secondHalf, end, start;
if (i>0) {
firstHalf = arr.slice(0, i);
secondHalf = arr.slice(i + 1, arr.length);
}
//this should get you started. Can you think of what edge cases you should test for to fix?
//what happens when point is at the start or the end of the array?
When splitting the array you are going to want to create two new arrays that will include what you are splitting, for example arr1 and arr2. To populate this arrays you are going to want to do something like this:
var arr1, arr2; // new arrays
int position = 0; // start position of second array
for(int i = 0; i <= arr.length(); i++){
if(arr[i] = point){ //when it finds the variable it stops adding to first array
//starts adding to second array
for(int j = i+1; j <= arr.length; j++){
arr2[position] = arr[j];
position++; //because we want to add from beginning of array i used this variable
}
break;
}
// add to first array
else{
arr1[i] = arr[i];
}
}
There are different ways to do this! good luck!
Yet another suggestion:
var segments = arr.join( '' ).split( point ).map(function( part ) {
return part.split( '' );
});
now segments contains an array of arrays:
[["a", "b"], ["d", "e", "f"]]
and can get accessed like
segments[ 0 ]; // ["a", "b"]
segments[ 1 ]; // ["d", "e", "f"]
if you want to split into equal half; why no simple while loop ?
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
var c=[];
while(arr.length > c.length){
c.push(arr.splice(arr.length-1)[0]);
}
Kaboom :).
Separate two arrays with given array elements as string array and number array;
let arr = [21,'hh',33,'kk',55,66,8898,'rtrt'];
arrStrNum = (arr) => {
let str = [],num = [];
for(let i = 0;i<arr.length;i++){
if(typeof arr[i] == "string"){
str.push(arr[i]);
}else if(typeof arr[i] == "number"){
num.push(arr[i]);
}
}
return [str, num]
}
let ans = arrStrNum(arr);
let str = ans[0];
let num = ans[1];
console.log(str);
console.log(num);