How to get text by id from array? React - javascript

CurrentUserAnswerVariants:
{id: "4468cdc8-220d-4634-9d68-6c9920e0cb48", text: "Question 1",
minAnswersQuantity: 1, maxAnswersQuantity: 1, canComment: false,
canComment: false, currentUserAnswerVariants: ["ecc0b93c-8e3b-4661-8f2e-f5382a74d79b"], id: "4468cdc8-220d-4634-9d68-6c9920e0cb48" }
const answers = [];
this.setState({questionGroups}, () => {
this.state.questionGroups.map((questionGroup) => {
questionGroup.questions.map((question) => {
// questionGroup.questions.variants.map((variant) => {
const currentUserAnswerVariantsVariantIds = question.currentUserAnswerVariants.filter(variant => ["canComment"].indexOf(variant) === -1);
const currentUserAnswerVariantsVariantText = question.currentUserAnswerVariants.filter(variant => currentUserAnswerVariantsVariantIds === variant.id).text;
const answer = {
questionId: question.id
};
if (!isNull(question.currentUserAnswerComment)) {
answer["comment"] = question.currentUserAnswerComment;
}
if (currentUserAnswerVariantsVariantIds.length) {
answer["variantIds"] = currentUserAnswerVariantsVariantIds;
}
if (currentUserAnswerVariantsVariantText) {
answer["variantText"] = currentUserAnswerVariantsVariantText;
}
answers.push(answer);
console.log(questionGroup.questions.variants);
// });
});
});
});
};
How to get by currentUserAnswerVariants value text from variants array by id?
My array Please can u see this image where is my array and when i check some variant i have new array Answer array

function idEquals(idToCompare, question) {
return question.id.indexOf(idToCompare) === 0;
}
currentUserAnswerVariantsVariantIds = question.filter(idEquals.bind(this, currentUserAnswerVariants));
Does this work?
It's something along these lines, and you may edit the following code accordingly.

$var = $('#id').val();
$var['text'];
-> only if you need single id text
-> or use foreach on id and push the each result into one blank array and print array

Related

How to insert key in object based on Id

I have an array of object, I want to add key in my specifi object of array when Id is matched. I have tried this:
this.data.forEach(value => {
if (value.Id === attachmentDataId) {
AttachmentTypeId: this.attachmentRecord.AttachmentType;
}
});
But it's not working and it's not giving any error also
Try this out :
let data = [{ id: 1 }, { id: 5 }];
const attachmentDataId = 5;
const attachmentRecord = { AttachmentType: "AttachmentType" };
data.forEach(value => {
if (value.id === attachmentDataId) {
value.AttachmentTypeId = attachmentRecord.AttachmentType;
}
});
The stackblitz example: https://stackblitz.com/edit/js-nrhouh
You could use the index parameter of forEach function to access the specific object of the array.
this.data.forEach((value, i) => {
if (value.Id === attachmentDataId) {
this.data[i] = {
...this.data[i],
AttachmentTypeId: this.attachmentRecord.AttachmentType
};
}
});
Inside the if block, you could also instead do
this.data[i]['AttachmentTypeId'] = this.attachmentRecord.AttachmentType;
I just find using the spread operator cleaner.
use javascript map() method.
Map() return a new array, it takes a callback, iterates on each element in that array
const updatedData = data.map(res => {
if(res.id === attachmentDataId) {
res.AttachmentTypeId = attachmentRecord.AttachmentType;
}
return res
})

Checking and displaying values of array compared to another array in React

One data set is an object of arrays of ids and another is an object of arrays of ids and names. What I'd like to do is check if the ids from the first data exist in the second data set and if they do then display the names.
This is what is being called by the component, which works correctly:
<td>Genre</td>
<td>{this.matchGenres(this.props.movie.genre_ids, this.props.genres)}</td>
And this is the function that I can't get to work:
matchGenres = (genres, genreList) => {
genres.forEach((genre) => {
genreList.filter((list) => {
return list.id === genre;
}).map((newList) => {
return newList.name;
});
});
}
It looks like the operation performs correctly and returns the right names when I console.log it! But! its not showing up in the component on render.
const genres = [{
id: 1,
name: "Jazz Music"
}, {
id: 2,
name: "Something"
}];
const genreList = [1, 10, 100];
matchGenres = (genres, genreList) => genres
.filter(genre => genreList.includes(genre.id))
.map(genre => genre.name);
const matchedGenres = matchGenres(genres, genreList);
console.log(matchedGenres);
But! its not showing up in the component on render.
Its because your function doesn't return anything. You return inside filter and map and your function does not return anything. Also note that forEach always return undefined
You just need a minor change. Try this
let genres = ["1", "2", "3"];
let genreList = [{
id: "2",
name: "Two"
}, {
id: "32",
name: "Three"
}]
matchGenres = (genres, genreList) => {
return genreList.filter((list) => {
// findIndex return array index if found else return -1 if not found
return genres.findIndex(genere => genere === list.id) > -1;
}).map(list => list.name);
}
console.log(matchGenres(genres, genreList));
This is the solution that ended up working:
if (genreList.length !== 0) {
return genres.map(genre => genreList.find(list => list.id === genre)).map((newList) => newList.name) + ',';
}
For some reason the value of GenreList, which is an array, was showing up as empty for the first couple times the function is call. Thats another problem I'll have to look at but the if statement solves for it for the time being.

Convert string into nested objects and arrays

I am in a project where the previous guy did some strange routing and basically I get slugs from contentful in the form of strings which I put in an array ["/api/", "/docs/getting-started/", "/docs/, "/plugin/", "/plugin/user/", "/plugin/profile/"......]
Now I need to convert it in the form of an array
let cleanedSidebarContents = [{
title:null,
pages:[
{title:"api",
path:"/api/"
},
{title:"docs",
path:"/docs/"
},
{title:"plugin",
path:"/plugin/"
},
]
},
{
title:"plugin",
pages:[
{title:"user",
path:"/plugin/user/"
},
{title:"profile",
path:"/plugin/profile/"
},
]
},
{
title:"docs",
pages:[
{title:"getting-started",
path:"/plugin/getting-started/"
},
]
}
]
So currently what I am doing is this -
//-------Format sidebar data--------------->
let cleanedSidebarContents = [];
(function cleanSidebarContents() {
let sideBarContentsContentful = [];
cleanContentfulEdges.forEach(edge => {
let slug = edge.node.slug;
//split string into titles and remove empty spaces
let routeMapArray = slug.split("/").filter(x => x != "");
if (routeMapArray.length > 1) {
sideBarContentsContentful.push({
title: routeMapArray[0],
page: {
title: routeMapArray[routeMapArray.length - 1],
path: edge.node.slug
}
});
} else {
sideBarContentsContentful.push({
title: null,
page: {
title: routeMapArray[routeMapArray.length - 1],
path: edge.node.slug
}
});
}
});
let titles = [];
for (let i = 0; i < sideBarContentsContentful.length; i++) {
titles.push(sideBarContentsContentful[i].title);
}
//clean duplicate entries
titles = titles.filter(function (item, index, inputArray) {
return inputArray.indexOf(item) === index;
});
titles.sort();
titles.map(item => {
cleanedSidebarContents.push({
title: item,
pages: []
})
});
sideBarContentsContentful.forEach(item => {
for (let i = 0; i < cleanedSidebarContents.length; i++) {
if(cleanedSidebarContents[i].title === item.title){
cleanedSidebarContents[i].pages.push(item.page)
}
}
});
}());
//----------------------------------------->
I am first splitting all strings and putting the titles in a titles array then removing duplicates and mapping data accordingly.
I just feel like this is really bad code and there is a better way I just cannot figure out.
You could create a mapper object which maps the objects in the output with the title in the root of each object. split at the / to get all the chunks of path. .filter(Boolean) removes all the empty string created from beginning and end of the string. If there is only one match, then it belongs to the default null object. Else, use the first key in the matches as a key in the accumulator.
const input = ["/api/", "/docs/getting-started/", "/docs/", "/plugin/", "/plugin/user/", "/plugin/profile/"];
const mapper = input.reduce((acc, path) => {
let matches = path.split(/\//).filter(Boolean),
mapperKey = null;
if (matches.length > 1)
mapperKey = matches[0];
if (!acc[mapperKey])
acc[mapperKey] = { title: mapperKey, pages: [] };
const title = matches.pop();
acc[mapperKey].pages.push({ title, path });
return acc;
}, {})
const output = Object.values(mapper);
console.log(output)

Javascript forEach where value equals value in different array

Javascript:
$(document).ready(function() {
const ores = "../js/json/oreList.json";
const priceURL = "https://esi.tech.ccp.is/latest/markets/prices/?datasource=tranquility";
let oreArray = [];
let priceArray = [];
let total = 0;
// Retrieve list of ores
function getOres() {
$.getJSON(ores, function(ores) {
ores.forEach(function(ore) {
total++;
if (total === 48) {
getPrices();
}
oreArray.push(ore);
});
});
}
// Retrieve all items & prices via API
function getPrices() {
$.getJSON(priceURL, function(prices) {
prices.forEach(function(data) {
priceArray.push(data);
console.log(data);
});
});
}
getOres();
});
The first function creates an internal array from my .JSON file and the second function creates an internal array from the URL.
In the first array oreArray, an object looks like this:
{ id: 1234, name: "Title" }
In the second array priceArray, an object looks like this:
{ type_id: 1234, average_price: 56.34 }
My oreArray has 48 objects and unfortunately the priceArray has about 11,000 objects. I need to create a new array by comparing the two arrays and building new objects, where the ID's match. So for example objects in newArray would look like:
{ id: 1234, name: "Title", average_price: 56.34 }
Basically I'm having trouble figuring out the logic for:
For each object in oreArray, find the object with the same ID value in priceArray and append the new array with a new object using values from both arrays.
I would do it this way:
const ores = "../js/json/oreList.json",
priceURL = "https://esi.tech.ccp.is/latest/markets/prices/?datasource=tranquility";
let oreArray,
priceArray,
joinedArray = [];
function getOres() {
$.getJSON(ores, function(ores) {
oreArray = ores;
getPrices();
});
}
function getPrices() {
$.getJSON(priceURL, function(prices) {
priceArray = prices;
joinPrices();
});
}
function joinPrices() {
oreArray.forEach(function(ore) {
var matchingPrice = getMatchingPrice(ore);
if(matchingPrice !== false) {
joinedArray.push({
id: ore.id,
name: ore.name,
average_price: matchingPrice.average_price
});
}
});
}
function getMatchingPrice(ore) {
for(var i=0; i<priceArray.length; i++) {
if(priceArray[i].type_id === ore.id) {
return priceArray[i];
}
}
return false;
}
getOres();
I think that a good way to approach this problem is by changing the data structure of the average prices a little bit.
Instead of having them in an array, where each item has type_id and average_price field, you might want to consider using an object to store them, where the key is the type_id and the value is the average_price.
To be more concrete, you can replace:
prices.forEach(function(data) {
priceArray.push(data);
});
With:
const pricesMap = {};
prices.forEach(price => {
pricesMap[price.type_id] = price.average_price
});
And when looping on the oreArray, you can access each product's average_price by simply referring to pricesMap[ore.id]
You can check out this JSBin: http://jsbin.com/fogayaqexe/edit?js,console
You can use reduce to loop over each oreArr item and collect the data you need in the accumulator:
var oreArr=[
{ id: 1234, name: "Title" },
{ id: 2234, name: "2Title" },
]
var priceArr= [
{ type_id: 1234, average_price: 56.34 },
{ type_id: 2234, average_price: 256.34 },
{ type_id: 3234, average_price: 56.34 },
{ type_id: 4234, average_price: 56.34 },
]
var resArr = oreArr.reduce((ac,x) => {
var priceMatch = priceArr.find( z => z.type_id === x.id )
if(! priceMatch)
return ac //bail out if no priceMatch found
var res = Object.assign({}, x, priceMatch)
ac.push(res)
return ac
},[])
console.log(resArr)
other methods used:
arrayFind to check intersection
Object.assign to create the merged object to populate the accumulator
I suggest you to change your small json as object
eg : '{"1234":{"id": 1234, "name": "Title" }}';
var json = '{"1234":{"id": 1234, "name": "Title" }}';
oreArray = JSON.parse(json);
alert(oreArray['1234'].name); // oreArray[priceArraySingle.id].name
we can easily match priceArray id with oreArray.

Javascript Loops: for-loop works but not map?

I'm working with mockData for a web app and I'm trying to loop over nested objects. My problem is that a for loop works but not array.map and don't know why.
Here is the for loop:
for (let i = 0; i < fakeChartData.length; i++) {
for (let j = 0; j < fakeChartData[i].poll.length; j++) {
if (fakeChartData[i].poll[j].id === id) {
return fakeChartData[i].poll[j]
}
}
}
And here is the map loop:
fakeChartData.map(data => {
data.poll.map(data => {
if (data.id === id) {
return data;
}
});
});
My Data structure:
fakeChartData = [
{
id: '232fsd23rw3sdf23r',
title: 'blabla',
poll: [{}, {}]
},
{
id: '23dgsdfg3433sdf23r',
title: 'againBla',
poll: [{}, {}]
}
];
I'm trying to load the specific object with the id passed to it on onClick method.
Here is the full function:
export const fetchPollOptById = (id) =>
delay(500).then(() => {
for (let i = 0; i < fakeChartData.length; i++) {
for (let j = 0; j < fakeChartData[i].poll.length; j++) {
if (fakeChartData[i].poll[j].id === id) {
return fakeChartData[i].poll[j]
}
}
}
});
A return statement inside a for loop causes your function to return. However, a return statement inside a .map() function's callback only returns the callback and this returned value is then placed in the new array. Please see the documentation.If you really want to be using .map(), you could do it like this:
export const fetchPollOptById = (id) => {
var result;
fakeChartData.map(data => {
data.poll.map(data => {
if (data.id === id) {
result = data;
return data;
}
});
});
return result;
}
note: I also assume that your poll objects have an id field like this:
fakeChartData = [
{
id: '232fsd23rw3sdf23r',
title: 'blabla',
poll: [
{id: 'pollId1', otherField: 'blah'},
{id: 'pollId2', otherField: 'blah'}
]
},
{
id: '23dgsdfg3433sdf23r',
title: 'againBla',
poll: [
{id: 'pollId3', otherField: 'blah'},
{id: 'pollId4', otherField: 'blah'}
]
}
];
You can then get the poll data like this:
fetchPollOptById("pollId3"); //returns {id: "pollId3", otherField: "blah"}
If I'm right about what you're trying to do, this should work:
return fakeChartData.reduce((acc, data) => acc.concat(data.poll), [])
.filter(pollObj => pollObj.id === id)[0]
First it makes an array containing all the poll objects from different data objects, then it filters them to find the one with the correct id and returns that object.
As to why your approach using map does not work: you are using it in the wrong way. What map does it to take a function and apply it to every member of an array.
Here's an array and function kind of like yours:
const arr = [1,2,3]
const getThingById(id) => {
var mappedArray = arr.map(x => {
if(x === id) return x
})
console.log(mappedArray) // [3]
}
getThingById(3) // undefined
This won't work. getThingById has no return statement. The return statement return x is returning something from the function that is passed into map. Basically, you shouldn't be using map to do what you're trying to do. map is for when you want to return an array.
Try this
fakeChartData.map(data => {
var result = data.poll.map(data => {
if (data.id === id) {
return data;
}
});
return result;
});
It should work. And yeah you should use find() instead of map() I think.
A bit long implementation:
let results = fakeChartData.map(data => {
let innerResult = data.poll.filter(data => {
if (data.id === id) {
return data;
}
return innerResult.length ? innerResult[0] : null;
});
})
.filter(x => (x !== null));
let whatYouwant = results.lenght ? results[0] : null;
If you can use find() it would look nicer, but that depends on what browsers you need to support

Categories