Nested array not returning expected value - javascript

I am trying to get access to individual values in an array within an array, I have the overall array, which has arrays in it, and then within that, I want to be able to access those values.
I would also likely assign each of those values to variables.
Essentially I am trying to iterate through what would become a grid of values (an array within an array) using JS.
1) I've tried accessing the value by pushing the row values into the array as a JSON string and then mapping it as array.map => row.map and then mapping it into individual elements
2) I've tried 'destructuring' the object but that did not seem to go anywhere either.
async function dataFormat(worksheet, rowNumber) {
csvWorkbook = workbook.csv.readFile("./uploads/uploadedFile.csv");
await csvWorkbook.then(async function(result) {
let restarts = 0;
let nullCounts = true;
let thermostatRows = [];
// you have to define THEN destructure the array
// const [serial,date,startDate,endDate,thing3,thing4,thing5] = firstTemps
worksheet.eachRow({ includeEmpty: true }, function(row, rowNumber) {
if (rowNumber > 6) {
Rows.push(`${JSON.stringify(row.values)}`);
}
});
console.log(thermostatRows[0])
})
};
Here is my function that returns the first row. If I put Rows[0][0] I get a letter.
here is the return of Rows[1]
[null,"2018-12 03T05:00:00.000Z","16:35:00","heat","heatOff", "hold","Home",70.1,70.1,69.8,43,33.8,0,0,15,15,null,69.8,43,1]
Which makes sense as it is the first row.
but logging Rows[0][0] gives me the first letter of null (first value in the array)
Lastly ,
[ '[null,"2018-12-02T05:00:00.000Z","23:25:00","heat","heatOff","auto","Home",72,72,72,47,41.3,0,0,0,0,null,72,47,0]',
'[null,"2018-12-03T05:00:00.000Z","16:35:00","heat","heatOff","hold","Home",70.1,70.1,69.8,43,33.8,0,0,15,15,null,69.8,43,1]',
'[null,"2018-12 03T05:00:00.000Z","16:40:00",null,null,null,null,null,null,null,null,33.8,0]'
Is the approximate log if I log Rows without anything else - to give you an idea of the whole situation.
edit: my function now looks like this, why would it return undefined?
if (rowNumber > 6) {
thermostatRows.push((row.values));
}
});
thermostatRows.map(thermostatRow => {
// let [date,time,SystemSetting,systemMode,calendarEvent,ProgramMode,coolSetTemp,HeatSetTemp,currentTemp,currentHumidity,outdoorTemp,windSpeed,coolStage1,HeatStage1,Fan,DMOffset,thermostatTemperature,thermostatHumidity,thermostatMotion] = thermostatSettings
console.log(date,time,SystemSetting)
})
})
};```
FINAL UPDATE
It works I figured out the undefined deal myself- try this. (this is with the excel.js library)
async function dataFormat(worksheet, rowNumber) {
csvWorkbook = workbook.csv.readFile("./uploads/uploadedFile.csv");
await csvWorkbook.then(async function(result) {
let restarts = 0;
let nullCounts = true;
let thermostatRows = [];
let thermostatSettings = []; // you have to define THEN destructure the array
// const [serial,date,startDate,endDate,thing3,thing4,thing5] = firstTemps
worksheet.eachRow({ includeEmpty: true }, function(row, rowNumber) {
if (rowNumber > 6) {
thermostatRows.push((row.values));
}
});
thermostatRows.map(thermostatRow => { [,date,time,SystemSetting,systemMode,calendarEvent,ProgramMode,coolSetTemp,HeatSetTemp,currentTemp,currentHumidity,outdoorTemp,windSpeed,coolStage1,HeatStage1,Fan,DMOffset,thermostatTemperature,thermostatHumidity,thermostatMotion] = thermostatRow
console.log(date,time,SystemSetting)
})
})
};

First, you need to be aware that Javascript arrays are zero-indexed. This means that to get the FIRST item, you use index 0. When you're calling Rows[1] you're actually getting the second item.
Second, you aren't creating a 2d array, you're creating a one dimensional array of strings.
Rows.push(`${JSON.stringify(row.values)}`);
This takes row.values and turns it into a string, interpolates it into another string, then pushes the final result into the array.
If you want an array inside the first array, which I assume row.values contains, do Rows.push(row.values);

Related

React.JS Storing mapped API repsonse into a new array based on matching values

Using React, I have data from an API response. I mapped the data and am storing the visitID, which would be the main identifier, into a variable. What I would like to do is look for any matching visitID values and store them into a new array, the issue I'm having is each instance is being stored in it's own array, for example:
['7065682'] at Index 0
['7065682'] at Index 1
['7065682'] at Index 2
['7047674'] at Index 3
['7047674'] at Index 4
I would like to look through each iteration and check all, put matching values into it's own array so I can write some logic based off each unique value. I just don't understand how to look through the next iteration. Here's my code, and the function 'duplicateVisitID' that I've been trying, but it doesn't give me the results I'm looking for.
{
Object.keys(this.state.EncounterData).length !== 0 ?
Object.values(this.state.EncounterData).map((encounter, i) => {
const visitID = [encounter.resource.identifier[1].value];
console.log(visitID, i);
const duplicateVisitID = function (visitID) {
if (visitID[i] === visitID[i])
return [visitID.concat(visitID[i])]
}
I am not sure what do you want to do, but if I understood right you want new array with only strings that are unique, not repeating. If yes see the code below. This is not the best performing one because of iteration inside iteration, but it will work for you. You can optimize it later by applying some algorithms.
The newArr is equal to ['7065682', '7047674']
const EncounteredData = [['7065682'], ['7065682'], ['7065682'], ['7047674'], ['7047674']];
const newArr = [];
for(let i of EncounteredData) {
for(let j of EncounteredData) {
if((i[0] !== j[0]) && !newArr.includes(i[0])) newArr.push(i[0]);
}
}
console.log(newArr);
If I understand correctly, you want an array of unique values? If so then you can use the map function and add any unique values to an array if the value is not already in it:
const uniqueVals = [];
EncounteredData.map((visitID) => {
if (!uniqueVals.includes(visitID[0])) {
uniqueVals.push(visitID[0]);
}
});

JavaScript - Return individual values from one array, inside of a for-of loop calling another array

I'm returning two values, svcCenterBands sortedBands, from one function and calling sortedBands inside a for of loop inside of another function.
svcCenterBands is an array of objects inside of the getMileageBand function that returns an array of unique objects that are string values representing a range of miles.
const getMileageBand = refSrcData => {
const mileageBand = refSrcData.data.map(e => e['97']); // Mileage Band Name
// Reduce the array to only unique values, no repeats
const svcCenterBands = mileageBand.reduce((unique, i) => {
if (!unique.some(obj => obj.label === i.label && obj.value === i.value)) {
unique.push(i);
}
return unique;
}, []);
// Get only the values from svcCenterBands
const numberedBands = svcCenterBands
.map(band => Object.values(band))
.join()
.split('-')
.map(str => str.split(',')[0]);
// Sort numberedBands in ascending order
const sortedBands = numberedBands
.map(Number)
.sort((first, next) => first - next);
console.log(svcCenterBands, sortedBands);
return [svcCenterBands, sortedBands];
};
sortedBands goes a bit further and takes svcCenterBands, grabs only it's last value and converts that to a number and sorts it. For example, if svcCenterBands returns a value of ["0-30"], sortedBands takes that string inside of the array and extracts the number past the hyphen, converts it to a number and sorts all array values in ascending order.
Inside of another function, I'm calling getMileageBand and running sortedBands (getMileageBand(facData)[1]) through a for of loop.
const mileageRanges = getMileageBand(facData)[0];
const mileageBand = getMileageBand(facData)[1];
// generate radius for each mileage band, mileage === coordinates
for (mileage of mileageBand) {
// for (mileage of getMileageBand(facData)) {
...
// console.log(mileageRanges.map(range => range.value));
const mileageValue = `${mileageRanges.map(range => range.value)} miles`;
...
I can get the values for sortedBands no problem which is what I need to generate my radial bands on my map.
But I'm trying to iterate through the values of svcCenterBands inside of the for (mileage of mileageBand) loop, but I'm getting the array of objects when I log mileageRanges inside of the mileageBand band for loop.
If i log mileageRange[mileage] with the for of index, I only get the first value in mileageRange and undefined for the rest.
What I would like to see is the values inside of the array of objects by their range, which I can get when I call getMileageBand but I can't get these values inside of the for of loop.
This is what I'm trying to get inside of the for of loop:
This is what shows up on my screen beneath my map with radial bands.
Ultimately, I'd like each card to show a sequence of 0-30, 31-60, etc. instead of all values being displayed in each card.
I can't include all of my code to test because it's too much and too many environment variables to extract the data I'm pulling from the database, so I included as much code as I could to back up my question.
It seems like you want to grab the element from mileageRanges which is at the same index as the current element of mileageBand in your for..of loop. I would suggest not using for..of in this case as I dont believe it provides the index. Here is a simple for loop.
const [mileageRanges, mileageBand] = getMileageBand(facData); // just call that expensive function once.
for (let i=0; i < mileageBand.length; i++) {
const mileage = mileageBand[i];
const mileageRange = mileageRanges[i].value;
}

Looping throw objects in array for specific returns only one object

I have an array of objects, and Would like to loop through them searching for a specific field, and create a new array that returns objects where that field is equal to what I give it. This works if there's only one object with a field like that, but when there are more, It only returns the first one. I need to return them all
const allPosts = [{name:'Post About Health', postCategory:'Health'}, {name:'Post About Money', postCategory:'Money'}, {name:'Post About Health 2', postCategory:'Health'}]
filterPosts('Health')
const filterPosts = (categ) => {
const filterThroughPosts = (category, post) => {
for (let i=0; i < post.length; i++){
if(post[i].postCategory === category){
return [post[i]]
}
}
}
const returnFilteredPosts = filterThroughPosts(categ, allPosts);
console.log(returnFilteredPosts) // > Returns only first object where postCategory == health, I need to return both. (Returns [{name:'Post About Health', postCategory:'Health'}]
//Should return [{name:'Post About Health', postCategory:'Health'}, [{name:'Post About Health 2', postCategory:'Health'}]
}
}
You can use Array.filter().
const filterPosts = (categ) => {
return allPosts.filter(elm => elm.postCategory === categ);
}
filterPosts('Health');
You are returning as soon as you find an object that matches your search criteria, that's why it returns an array with one item in it.
You can use filter to get your array of objects.

Javascript remove the occurrences of item by matching condition

I have an arrray as below:
var testArr = [ "1,A", "2,B", "1,D", "3,A" ]
I would like to get the result as
var result = [ "1,A", "2,B", "3,A" ]
I have tried to using filter but I cannot get the output. Could anyone please help me for this?
const testArr = ['1,A', '2,B', '1,D', '3,A'];
const result = testArr.reduce((val, cur) => {
if (!val.some((v) => v.includes(cur[0]))) {
val.push(cur);
}
return val;
}, []);
console.log(result);
var newra = oldra.filter(compare_function);
The above function 'filter' creates a new empty array and iterates through the elements in oldra. If the elements value when passed to compare_function(element_value) returns true, it will be added to the new array otherwise it will be skipped. The filter function continues iterating through the oldra building a new array as it goes until all elements are processed. The filter function then returns the new array.
The compare_function(element_value) expects the value of an element of an array to be passed to it. The programmer performs some calculation on the element_value and returns a true or false based on this calculation according to whether it should be included in the newra or not.

Using map reduce etc, how would you find the first item matching a certain criteria in a nested array, and stop once found?

How would you find the first item matching a certain criteria in a nested array, and stop once found?
In a 1D array, this is what the Array.find function is for, but how would you do it for a 2D array, and, even neater, for n-dimension array?
Also, I'm trying to come up with a neat solution using es6 and array functions such as find, map, reduce etc, rather than using more traditional loops and variables to maintain state (see one such old-school solution below).
The data may look something like this
const data = [
{arr: [{val:6,name:'aaa'},{val:4,name:'bbb'},{val:8,name:'ccc'}]},
{arr: [{val:3,name:'mmm'},{val:5,name:'nnn'},{val:9,name:'ppp'},{val:5,name:'ooo'}]}
]
I'm hoping I can do something similar to array.find (and its predicate / testing function), but I need to go deeper and find eg the first item with val=5. For the data above, I'd expect to get the item with name 'nnn' (not 'ooo'), and have the process end once the first item is found. Similar to Array.find, I want to avoid processing the rest of the data once a matching item is found.
One boring old way to do it would be something like this, with a loop, but that's... boring, and not as neat as the lovely array functions :)
let found
// loop through all data entries in the outer array
for (const d of data) {
// attempt to find a matching item in the inner array.
// using array.find means we stop at the first match, yay!
const theItem = d.arr.find(item => {
return myPredicate(item)
})
// we also need to break out of the loop. ugh!
if (theItem) {
found = theItem
break
}
}
// return what we found (may be undefined)
return found
Now, I realise that I can do something with find() and some(), say, similar to the answer here ES6 - Finding data in nested arrays, but the problem is that using find on the outer array means that we get back the first item of the outer data array, whereas I want an item from the inner arr array.
const outer = data.find(d => {
return d.arr.some(item => {
return myPredicate(item)
})
})
I would then have to process outer AGAIN to find the item in outer.arr, something like
outer.arr.find(item => myPredicate(item))
This doesn't sit well with me, as the call to some(...) has already gone through and found the matching inner item!
I thought this would be straight forward, and maybe it is, but for one reason or another I got stuck on this little challenge.
I've also looked at the nice traverse library (https://www.npmjs.com/package/traverse), but again that seems to be more about traversing through a whole tree rather than stopping and returning once a particular node is found.
Anyone up for a challenge? ;)
The easiest (though slightly ugly) solution would be to assign the matching item to an outer variable when found:
let foundNested;
data.some(subarr => (
subarr.some((item) => {
if (myPredicate(item)) {
foundNested = item;
return true;
}
});
});
You might use .reduce to avoid assigning to an outer variable:
const myPredicate = ({ val }) => val === 5;
const data = [
{arr: [{val:6,name:'aaa'},{val:4,name:'bbb'},{val:8,name:'ccc'}]},
{arr: [{val:3,name:'mmm'},{val:5,name:'nnn'},{val:9,name:'ppp'},{val:5,name:'ooo'}]}
];
const found = data.reduce((a, { arr }) => (
a ||
arr.find(myPredicate)
), null);
console.log(found);
Problem is, the reduce won't short-circuit - it'll fully iterate over the outer array regardless. For true short-circuiting, I think I'd prefer using a for..of loop:
const data = [
{arr: [{val:6,name:'aaa'},{val:4,name:'bbb'},{val:8,name:'ccc'}]},
{arr: [{val:3,name:'mmm'},{val:5,name:'nnn'},{val:9,name:'ppp'},{val:5,name:'ooo'}]}
];
function findNested(outerArr, myPredicate) {
for (const { arr } of outerArr) {
for (const item of arr) {
if (myPredicate(item)) {
return item;
}
}
}
}
const myPredicate = ({ val }) => val === 5;
console.log(findNested(data, myPredicate));
You'll want to write your own find function that doesn't take a predicate but a result-producing callback:
function find(iterable, callback) {
for (const value of iterable) {
const result = callback(value);
if (result !== undefined)
return result;
}
}
With that, you can write
const data = [
{arr: [{val:6,name:'aaa'},{val:4,name:'bbb'},{val:8,name:'ccc'}]},
{arr: [{val:3,name:'mmm'},{val:5,name:'nnn'},{val:9,name:'ppp'},{val:5,name:'ooo'}]}
];
console.log(find(data, ({arr}) => find(arr, o => o.val == 5 ? o : undefined)));
Alternatively, if you want to get all results, flatMap is the perfect tool:
data.flatMap(({arr}) => arr.filter(({val}) => val == 5));
Sure, why not. I'm up for it. This can probably be improved upon. But this will work. Let's say you are trying to find an object with id of 5 in a multidimensional array.
const arr = [[[{id: 1}], [{id: 2}]], [[{id: 3}]], [[{id: 4}], [{id: 5}], [{id: 6}]]]
function findObject (obj) {
if (Array.isArray(obj)) {
const len = obj.length
for (let i = 0; i < len; i++) {
const found = findObject(obj[i])
if (found) {
return found
}
}
} else if (obj.id === 5) { // Put your search condition here.
return obj
}
}
const obj = findObject(arr)
console.log('obj: ', obj)
This seems to work, but, in my opinion, it's still not clean with that 'found' variable sitting outside the main block and being assigned from inside the nested find block. It's better though. Thoughts?
let found
data.find(d =>
d.arr.find(item => {
found = myPredicate(item) ? item : void 0
return found !== void 0
}) !== void 0
)
return found

Categories

Resources