I have two different arrays and I am trying to filter the one while looping the other.
const serviceCodes =
[
{
...otherStuff...
"codes": [
"786410010",
"787885010"
]
}
]
and
const laborCost =
[
{
"laborCode": "786410010",
"estimatedCost": {
"value": -1,
"currency": "USD"
}
},
{
"laborCode": "787885010",
"estimatedCost": {
"value": -1,
"currency": "USD"
}
}
]
I am looping through serviceCodes and trying to return only the object that matches the laborCode
const serviceMatchesRow = serviceCodes[0].codes.forEach((code) => {
return laborCost?.find(
(service) => service.laborCode === code,
)
})
This is returning undefined as forEach only runs through it, but if I use .map instead, then it return the 2 objects within laborCost. If I change for .find instead, than it returns an array with the laborCode itself ["786410010", 787885010].
So how can I get around this?
The desired output would be something like:
[{
"laborCode": "786410010",
"estimatedCost": {
"value": -1,
"currency": "USD"
}
}]
forEach method doesn’t return anything
so you should insert the matches objects in new array.
or use .map method
const serviceMatchesRow = [];
serviceCodes[0].codes.map((code) => {
serviceMatchesRow.push(laborCost.find((service) => {
return service.laborCode === code
}
));
});
Problem: You're trying to return from within the foreach block; that will not return anything thats why you see undefined.
Solution: Use map to return while iterating on an array.
const serviceMatchesRow = serviceCodes[0].codes.map((code) => {
return laborCost.find(
(service) => service.laborCode === code,
)
})
Working fiddle: https://jsfiddle.net/240z5u3f/3/
Related
I am trying to perform .toLocaleString() on each of the arrays elements.
I am performing this for example to change 1111' to 1,111`.
The data I am trying to access:
"Data": {
"id": 1182,
"time": 1637193600,
"symbol": "BTC",
"partner_symbol": "BTC",
"zero_balance_addresses_all_time": 882855842,
"unique_addresses_all_time": 920909797,
"new_addresses": 476543,
"active_addresses": 992178,
"average_transaction_value": 18.723511893530098,
"block_height": 710345,
"hashrate": 163489266.17996278,
"difficulty": 22674148233453.105,
"block_time": 595.6643356643356,
"block_size": 1267871,
"current_supply": 18877162,
"transaction_count": 293867,
"transaction_count_all_time": 688002252,
"large_transaction_count": 29400
}
My code in attempt to manipulate the array:
getCryptoBlockchainData(selectedCrypto).then(cryptoTradingSignal => {
if (cryptoTradingSignal.hasOwnProperty('id')) {
cryptoTradingSignal.forEach(function (item, i) {
this[i] = item.toLocaleString();
}, cryptoTradingSignal);
return this.setState({cryptoBlockchainData: cryptoTradingSignal});
} else {
return this.setState({cryptoBlockchainData: undefined});
}
});
}
You can't forEach over the properties of an object. You can convert it to an array, do your thing, then convert it back to an object.
getCryptoBlockchainData(selectedCrypto).then(cryptoTradingSignal => {
if (cryptoTradingSignal.hasOwnProperty('id')) {
const newSignal = Object.fromEntries(
Object.entries(cryptoTradingSignal).map(([k, v]) => ([k, v.toLocaleString()]))
);
return this.setState({cryptoBlockchainData: newSignal});
} else {
return this.setState({cryptoBlockchainData: undefined});
}
});
you could probably use Array.prototype.map() for that.
For your code maybe something like
const newArray = Object.keys(object["Data"]).map(item => object[item].toLocaleString()));
See the docs here.
You can iterate through the object keys using the Object.keys() function and change the values you want.
const dataObj = {
"id": 1182,
"time": 1637193600,
"symbol": "BTC",
"partner_symbol": "BTC",
"zero_balance_addresses_all_time": 882855842,
"unique_addresses_all_time": 920909797,
"new_addresses": 476543,
"active_addresses": 992178,
"average_transaction_value": 18.723511893530098,
"block_height": 710345,
"hashrate": 163489266.17996278,
"difficulty": 22674148233453.105,
"block_time": 595.6643356643356,
"block_size": 1267871,
"current_supply": 18877162,
"transaction_count": 293867,
"transaction_count_all_time": 688002252,
"large_transaction_count": 29400
}
Object.keys(dataObj).forEach(key => dataObj[key] = dataObj[key].toLocaleString());
console.log(dataObj);
EDIT:
Incase your Object is nested as in your example, you also need to use the 'Data' key:
Object.keys(dataObj['Data']).forEach(key => dataObj['Data'][key] = dataObj['Data'][key].toLocaleString());
I have the following javascript array (I'm having fun with map() today) - I want to be able to return the pages data but have the page id as the key and the index for the position of that page within the pages array as the value. What am I doing wrong?
let result = [
{
"id": 10000089,
"units": [
{
"id": 10000200,
"pages": [
{
"id": 100000882
}
]
},
{
"id": 10000340,
"pages": [
{
"id": 100000912
},
{
"id": 100000915
},
{
"id": 100000919
}
]
}
],
}
];
// this is my attempt but doesn't return in the intended format below
result.flatMap(el => el.units.map((e, i) => (e.pages)));
Expected output
pages = [
100000882 => 0,
100000912 => 0,
100000915 => 1,
100000919 => 2,
]
Here is a stackblitz to the code
https://stackblitz.com/edit/js-mc9rqe
Your expected output should be an object instead of an array. You can use Array.prototype.flatMap, Object.fromEntries for achieving the result.
let result=[{id:10000089,units:[{id:10000200,pages:[{id:100000882}]},{id:10000340,pages:[{id:100000912},{id:100000915},{id:100000919}]}]}];
const pages = Object.fromEntries(
result.flatMap(item => item.units.flatMap(unit => unit.pages.map((page,i) => ([page.id, i]))))
);
console.log(pages);
Note that, the Object.fromEntries() takes an array of arrays of a [key, value] pair and then converts them into an object. In your case the page.id would be the key and the index of the last map would be the value.
In your data, pages is also an array of objects. So, you need to loop through each page as well.
Using Array.flat
let result=[{id:10000089,units:[{id:10000200,pages:[{id:100000882}]},{id:10000340,pages:[{id:100000912},{id:100000915},{id:100000919}]}]}];
const getFormattedData = data => {
const res = data.map(datum => datum.units.map(unit => unit.pages.map(({ id }, i) => ({
[id]: i
}))));
return res.flat(2);
}
console.log(getFormattedData(result));
Using Array.flatMap
let result=[{id:10000089,units:[{id:10000200,pages:[{id:100000882}]},{id:10000340,pages:[{id:100000912},{id:100000915},{id:100000919}]}]}];
const getFormattedData = data => {
return data.flatMap(datum => datum.units.flatMap(unit => unit.pages.map(({ id }, i) => ({
[id]: i
}))));
}
console.log(getFormattedData(result));
Note that both of the above methods will result in Array of objects.
I am trying to reformat my list of objects by grouping a certain key pair in javascript.
Data Format
[{
"sccode": "sccode1",
"val": "1ADA"
}, {
"sccode": "sccode2",
"val": "1ADB"
}, {
"sccode": "sccode1",
"val": "1ADC"
}]
Expected Result
[{
"scCode": "sccode1",
"valCodes": ["1ADA", "1ADC"]
},
{
"scCode": "sccode2",
"valCodes": ["1ADB"]
}
]
I believe I could loop through the array and match my keys, but is there a quick way to reformat this without having to explicitly loop through? I've tried using a reduce function below, but it gives undefined errors with find, which i think has something to do with my formatting.
Tried (?) Code
const resp = data.reduce((acc, ele) => {
const ant = acc.find(x => x.sccode === ele.sccode);
}, []);
Would this do?
const src = [{"sccode":"sccode1","val":"1ADA"},{"sccode":"sccode2","val":"1ADB"},{"sccode":"sccode1","val":"1ADC"}],
result = src.reduce((r,{sccode,val}) => {
const match = r.find(({scCode}) => scCode == sccode)
match ?
match.valCodes.push(val) :
r.push({scCode:sccode, valCodes: [val]})
return r
}, [])
console.log(result)
.as-console-wrapper{min-height:100%;}
Try the following, I use a map to store a partial state to improve performances preventing to search sccode in an array for every initial object.
let partial = [{
"sccode": "sccode1",
"val": "1ADA"
}, {
"sccode": "sccode2",
"val": "1ADB"
}, {
"sccode": "sccode1",
"val": "1ADC"
}].reduce((map, obj) => {
if (!map[obj.sccode]) {
map[obj.sccode] = [obj.val];
} else {
map[obj.sccode].push(obj.val);
}
return map;
}, {})
Object.keys(partial).map(sccode => ({
sccode, valCodes: partial[sccode]
}));
try loaddash/groupby
let groupByResult = groupBy(data, function (n) {
return n.sccode
});
Check this code:
array.reduce(function(res, value){
if(!res[value.sccode]) {
res[value.sccode] = value;
res[value.sccode]['valCodes'] = []
result.push(res[value.sccode]);
}
res[value.sccode]['valCodes'].push(value.val);
return res;
} ,{});
I tested here and it works fine!
I use vue-multiselect to let user select items with filtering options:
query = "what user type in input field"
allLinks.filter(l=>l.labelName.includes(query))
and it works, but now I would like to extend the filtering to all properties of my object with this structure :
{
"labelName":"LK000056",
"extPort":{
"aPort":"EXTA-EQ001/board10port02",
"zPort":"EXTZ-EQ012/board09port02"
}
}
I would like with one query to get parent object if query match on labelName, aPort or zPort.
it is possible ? or maybe with a conditional way like :
allLinks.filter(l=>if(!l.labelName.includes(query)){l.extport.aPort.includes(query)}else{l.extport.zPort.includes(query)})
thank for helping me
forgive my approximate English I am French
You could recursively flatten the objects to array of strings, then search in them via Array.filter, Array.some & Array.includes:
const data = [{ "labelName":"LK000056", "extPort":{ "aPort":"EXTA-EQ001/board10port02", "zPort":"EXTZ-EQ012/board09port02" } }, { "labelName":"LK000057", "extPort":{ "aPort":"EXTA-EQ001/board123", "zPort":"EXTZ-EQ012/board333" } }]
const flatten = (obj, a=[]) => Object.values(obj)
.reduce((r,c) => (typeof c == 'object' ? flatten(c,a) : r.push(c), r), a)
const search = (d, t) =>
d.filter(x => flatten(x).some(x => x.toLowerCase().includes(t.toLowerCase())))
console.log(search(data, 'board123'))
console.log(search(data, 'LK000056'))
console.log(search(data, 'EXTZ-EQ012'))
Note that this is a generic approach and will work regardless of the nested levels of data, for example:
const data = [{
"A": {
"B": {
"C": {
"data": '11'
},
}
}
}, {
"D": {
"E": {
"data": '22'
}
}
}, {
"F": "33"
}]
const flatten = (obj, a = []) => Object.values(obj)
.reduce((r, c) => (typeof c == 'object' ? flatten(c, a) : r.push(c), r), a)
const search = (d, t) => d.filter(x =>
flatten(x).some(x => x.toLowerCase().includes(t.toLowerCase())))
console.log(search(data, '22'))
console.log(search(data, '11'))
console.log(search(data, '33'))
You can use Object.values to get the values of the object as an array, then use some to test if one or more items match.
const items = [{
"labelName": "LK000056",
"extPort": {
"aPort": "EXTA-EQ001/board10port02",
"zPort": "EXTZ-EQ012/board09port02"
}
}, {
"labelName": "234234",
"extPort": {
"aPort": "abc123",
"zPort": "1234567890"
}
}]
function search(query, data) {
return data.filter(i => {
if (i.labelName.includes(query)) return true
if (Object.values(i.extPort).some(v => v.includes(query))) return true
return false
})
}
console.log(search("EQ001", items))
console.log(search("1234567890", items))
console.log(search("lalalala", items))
if it can help I think found a functional solution let me know if something better can be done ...
allLinks.filter(l=>{
if (l.sdhPort.zSDHPort!=undefined && l.extPort.aPort.toUpperCase().includes(query.toUpperCase())){return true}
if (l.extport.zPort!=undefined && l.extPort.zPort.toUpperCase().includes(query.toUpperCase())){return true}
if (l.labelName!=undefined && l.labelName.toUpperCase().includes(query.toUpperCase())){return true}
})
wow thanks both of you !
it seems really interesting this technic ... but let me some time to understand it
what do think about what I found ?
best regards
I have a set of data which I have grouped by the key of the object - For each key of the object I need to produce an array of the id's . So instead of an array of object it is just a flat array of the id's.
I have managed to get the data back but can't seem to get just the id's out.
Here is the data set
let result = {
"age_group_ids": [
{
"id": 5
},
{
"id": 4
},
{
"id": 3
},
{
"id": 9
}
],
"family_group_ids": [
{
"id": 2
},
{
"id": 1
}
],
"earnings_group_ids": [
{
"id": 7
},
{
"id": 6
}
]
}
This is the function I have written but it does not seem to work.
Object.keys(result).forEach(key => {
return result[key].map(item => {
item.id
})
})
The end result I want an object like this
{"age_group_ids": [5,4, 3, 9],
"family_group_ids": [2, 1],
"earnings_group_ids": [7,6]
Instead of returning from the forEach, assign the results back the result[key]. Removed the curly brackets arround the item.id of the map, so value would be added to the array.
const result = {"age_group_ids":[{"id":5},{"id":4},{"id":3},{"id":9}],"family_group_ids":[{"id":2},{"id":1}],"earnings_group_ids":[{"id":7},{"id":6}]};
Object.keys(result).forEach(key => {
result[key] = result[key].map(item => item.id)
})
console.log(result);
let result = {"age_group_ids":[{"id":5},{"id":4},{"id":3},{"id":9}],"family_group_ids":[{"id":2},{"id":1}],"earnings_group_ids":[{"id":7},{"id":6}]};
function groupById(groups) {
return Object.keys(groups).reduce((result, key) => {
result[key] = result[key] || [];
result[key] = groups[key].map(o => o.id);
return result;
}, {});
}
console.log(groupById(result))
Use Array.prototype.reduce() instead of Array.prototype.forEach(), and Object.entries() for convenience so you don't have to use a scoped reference to result[key]. You can also use object destructuring to reference key, values, and id in a more concise way. Don't forget that you need to initialize acc to an empty object for the reduce() callback:
const result = {age_group_ids:[{id:5},{id:4},{id:3},{id:9}],family_group_ids:[{id:2},{id:1}],earnings_group_ids:[{id:7},{id:6}]}
const output = Object.entries(result).reduce((acc, [key, values]) => Object.assign(acc, {
[key]: values.map(({ id }) => id)
}), {})
console.log(output)