Formatting Arrays of Objects into Objects (ES6 Way) - javascript

I am trying to create a pretty Objects of arrays but this come instead.
{
"label": [
"Instagram"
],
"value": [
"#username"
]
}
So, how can I change it? What I want is to be like this
{
"label": "instagram",
"value": "#username"
},
I don't know how it happened, but my guess is it was the result of me using formik to define initialValues of a complex nested array from strapi. I was using array.map to map the objects. Hence perhaps thats why it was so messy.
So what is the solution for this? Formatting Arrays of Arrays into Objects? Merging? Converting? I have no idea what it was called. Thanks in advance for anybody replying this.
(updated) The initialValues:
const formik = useFormik({
enableReinitialize: true,
initialValues: {
name: vendor?.name || '',
description: vendor?.description || '',
company: {
social_media: [
{
label: vendor.company?.social_media.map((x) => x.label) || '',
value: vendor.company?.social_media.map((x) => x.value) || ''
}
]
}
},

You can use for..in and array join method
const data = {
"label": [
"Instagram"
],
"value": [
"#username"
]
};
for (let keys in data) {
data[keys] = data[keys].join(',')
};
console.log(data)

Array.map returns an array if you don't want any object use Array.foreach
Or
Use [...Array.map()]
label: [...vendor.company?.social_media.map((x) => x.label)]
value: [...vendor.company?.social_media.map((x) => x.value)

Related

Return all values of nested arrays using string identifier

Given an object searchable, is there a simple way of returning all the id values using lodash or underscore.js (or equivalent) where I can define the path to id?
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
I am looking to see if this is possible in a manner similar to how we can use lodash.get e.g. if we wanted to return the things array from searchable we could do
const things = _.get(searchable, 'things');
I can't seem to find anything similar in the documentation. I am looking for something
that could contain an implementation similar to:
_.<some_function>(searchable, 'things[].properties[].id')
Note: I am well aware of functions like Array.map etc and there are numerous ways of extracting the id property - it is this specific use case that I am trying to figure out, what library could support passing a path as a string like above or does lodash/underscore support such a method.
Found a solution using the package jsonpath
const jp = require('jsonpath');
const result = jp.query(searchable, '$.things[*].properties[*].id')
console.log(result);
// outputs: [ 'd1-i1', 'd1-i2', 'd2-i1', 'd2-i2' ]
you can do it easily in plain js
like this
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
const search = (data, k) => {
if(typeof data !== 'object'){
return []
}
return Object.entries(data).flatMap(([key, value]) => key === k ? [value]: search(value, k))
}
console.log(search(searchable, 'id'))
_.map and _.flatten together with iteratee shorthands let you expand nested properties. Every time you need to expand into an array, just chain another map and flatten:
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
// Let's say the path is "things[].properties[].id"
const result = _.chain(searchable)
.get('things').map('properties').flatten()
.map('id').value();
console.log(result);
<script src="https://cdn.jsdelivr.net/npm/underscore#1.13.4/underscore-umd-min.js"></script>

Filter on arrays on Objects inside array of Objects in JavaScript

I would like to get an array of the Main by category
[
{
"#id": "/api/main/7648",
"#type": "Main",
category: [{
name: "laboriosam"
}]
},
{
"#id": "/api/main/7647",
"#type": "Main",
category: [{
name: "foo"
},
{
name: "bar"
}
]
}
]
So I try:
console.log([...this.state.mains].filter(main => main.category.filter(category => category.name == "foo")))
But it returns me everything and I don't understand why?
Using Array.prototype.some, you can decide if the value is existed or not.
Using Array.filter function, it filters the true values only so it is needed to return boolean value on callback.
const input = [{
"#id": "/api/main/7648",
"#type": "Main",
category: [{
name: "laboriosam"
}]
},
{
"#id": "/api/main/7647",
"#type": "Main",
category: [{
name: "foo"
},
{
name: "bar"
}
]
}
];
console.log(input.filter(main => main.category.some(category => category.name == "foo")))
I find your question really hard to understand. If you want just the objects with #type = "Main" you can do
this.state.mains.filter(x => x["#type"] === "Main");
If you then want to filter those out who don't have a certain category you can add another filter like so:
this.state.mains
.filter(x => x["#type"] === "Main")
.filter(x => x.category.findIndex(c => c.name === "foo") !== -1);
Obviously in case of big array you also put both checks into one filter, but that might not be as readable.
Also note that [...this.state.mains].filter(...) is redundant, as .filter() already returns a new array.

Nested arrays with objects, lodash meanBy

Can someone please help me understand how to make this work. Everytime I feel like I start to understand arrays and objects in Javascript it turns out that I still don't.
I'm trying to get the average of all prices in the following datastructure by using lodash meanBy
[
{
date: "2019-12-17",
items: [
{ id: "1", state: "accepted", price: "90.5" },
{ id: "2", state: "rejected", price: "20.0" },
{ id: "3", state: "open", price: "10.5" },
]
},
{
date: "2019-12-18",
items: [
{ id: "4", state: "open", price: "450.0" },
{ id: "5", state: "rejected", price: "40.1" },
{ id: "6", state: "accepted", price: "50.9" },
]
}
]
If you provide the answer, can you also please try to explain how you select something nested in items, because that's as far as I get before I get lost.
In this case instead of selecting nested values, it's easier to flatten the items to a single array, and then apply _.meanBy(). In addition, the prices are strings, and not numbers, so you'll need to convert them.
Flatten the items to a single array with Array.flatMap(), and then use _.meanBy(), and get the numeric values of the prices:
const data = [{"date":"2019-12-17","items":[{"id":"1","state":"accepted","price":"90.5"},{"id":"2","state":"rejected","price":"20.0"},{"id":"3","state":"open","price":"10.5"}]},{"date":"2019-12-18","items":[{"id":"4","state":"open","price":"450.0"},{"id":"5","state":"rejected","price":"40.1"},{"id":"6","state":"accepted","price":"50.9"}]}]
const result = _.meanBy(_.flatMap(data, 'items'), o => +o.price)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Another approach is to get the general average, by getting the average of each items array separately , and then getting the average of all averages.
const data = [{"date":"2019-12-17","items":[{"id":"1","state":"accepted","price":"90.5"},{"id":"2","state":"rejected","price":"20.0"},{"id":"3","state":"open","price":"10.5"}]},{"date":"2019-12-18","items":[{"id":"4","state":"open","price":"450.0"},{"id":"5","state":"rejected","price":"40.1"},{"id":"6","state":"accepted","price":"50.9"}]}]
const result = _.meanBy(data, ({ items }) => _.meanBy(items, o => +o.price))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Find out if an object already exists in an array

I want to do a database operation only if my barcode is new to the structure.
My plan was either to use the function includes() or simply count the existence in the array.
I have found quite helpful code snippets like countDuplicate and the function include() to do the job but I guess my case is a little bit more specific.
But I not only have an object/array which consists of strings. (1st example)
I have an object which includes different objects and their properties.
//1st example (this works pretty well)
function countDuplicate(array, elem) { //just the special type of syntax for Vue/Node.js
return array.filter(item => item == elem).length;
}
var cars = ["Saab", "Volvo", "BMW", "BMW", "BMW"];
console.log(countDuplicate(cars, "BMW"); //will return 3
console.log(cars.includes("BMW")); //will return true
But as I said I have more a structure like that:
var object = {
sub_object1: { title: "test1", barcode: "0928546725" },
sub_object2: { title: "test2", barcode: "7340845435" },
};
How can I get the same results there?
My plan was to do it like that:
if(countDuplicate(object, "0928546725") == 0)
//... do my operations
But this not work because I don't really understand how I get into the structure of my objects. I experimented with different loops but nothing actually worked.
This is my array:
export default {
data() {
return {
form: {
items: [ //Barcodes
],
status: 1,
rent_time: Date.now()
},
submit: false,
empty: false,
}
},
____________________________________________________________________
Solutions:
I tried the following from #adiga and it works for the example but not for my real case.
This is a screen of my console:
So
A simple object.filter(a => a.barcode == elem) should work - #adiga
Like that?
countDuplicateBarcodes: function(obj, elem) {
//return Object.values(obj).filter(a => a.barcode == elem).length;
return obj.filter(a => a.barcode == elem).length;
}
Doesn't work anymore...
Get all the values of object in an array usingObject.values and then use filter
function countDuplicateBarcodes(obj, elem) {
return Object.values(obj).filter(a => a.barcode == elem).length;
}
const object = {
sub_object1: { title: "test1", barcode: "0928546725" },
sub_object2: { title: "test2", barcode: "7340845435" },
sub_object3: { title: "test3", barcode: "0928546725" }
};
console.log(countDuplicateBarcodes(object, "0928546725"))
If you just want to find a barcode in your object, then your question is a duplicate of for example
https://stackoverflow.com/a/46330189/295783
Changed to match you requirement:
const barcodes = {
sub_object1: { title: "test1", barcode: "0928546725" },
sub_object2: { title: "test2", barcode: "7340845435" },
};
const findMatch = (barcode, barcodes) => JSON.stringify(barcodes).includes(`"barcode":"${barcode}"`);
console.log(
findMatch("0928546725",barcodes)
)
Looking at your code, it appears like you actually use an array of objects and not a nested object. If that's the case, something like this should work:
let scannedTools = [
{barcode: "ABC", createdAt: "today"},
{barcode: "XYZ", createdAt: "123"}
];
function isAlreadyScanned(tool) {
return scannedTools.filter(t => t.barcode == tool.barcode ).length > 0
}
console.log(isAlreadyScanned({barcode: "ABC"}));
console.log(isAlreadyScanned({barcode: "ETRASDASD"}));
console.log(isAlreadyScanned({barcode: "XYZ"}));

javascript (reactJS) best way to access values in a child Array

I've got the following array:
This is an array of Users, and each User has an Attributes array.
Now I want to make a new array with users and only their attributes. Like this
users{
0: {
"phone_number",
"email"
}
}
What would be the best way to achieve this?
thanks
If you need Array of users which contains arrays with users attributes, then you can use Array.prototype.map method:
let users = [
{ Attributes: [ { Name: 'phone_number' }, { Name: 'email' } ] },
{ Attributes: [ { Name: 'phone_number1' }, { Name: 'email1' } ] }
];
let result = users.map((user) => user.Attributes.map((attr) => attr.Name));
console.log(result)

Categories

Resources