Move properties in objects according to their index - javascript

I've been trying to do this, and I've looked for the answer everywhere but no one seems to know or have the same problem.
What I want to do is: I have an array that looks like this
const myArray = [
{
nombre: 'String',
definicion: 'Whatever.',
duracion: 'Blah',
id: "Blah",
},
{
nombre: 'Name',
definicion: 'Short description.',
duracion: 'time',
id: "whatever again",
},
{
nombre: 'hello',
definicion: 'this is descripciĆ³n.',
duracion: 'time',
id: "the end",
},
I used map return (item. nombre, item. definicion, etc.) and have them separated in different divs, so I wanted to do nombre.onclick (CSS transition so that the its definition will be shown) but its not working. It either shows all definitions or none. Sometimes it shows one definition 3 times ( or the number of objects in the array)

Related

Separate big array from main component to a new file

I'm new in the front end world, and I currently working on Angular project with typescript, and I created an array in order to assign to an object, so I have something like this in my TS component:
formOptions = []
ngOnInit() {
this.formOptions = [{
id: 1,
description: 'First name'
},
{
id: 2,
description: 'Middle name'
}, {
id: 3,
description: 'Last name'
}...etc
}
As you can see the array it's going to be supper big, is there a way to move the array to separate file, then import it and just assign the object? If so, where is the common path to save this path of files and what extension I should use for it?
Try storing the array in a separate .json file. Then use fetch to load the file and parse the JSON. JSON is Javascript Object Notation and it will take an array (or object) exactly as you have it laid out in your code.
[{
id: 1,
description: 'First name'
},
{
id: 2,
description: 'Middle name'
}, {
id: 3,
description: 'Last name'
}...etc
}]
The first example at MDN does exactly what I describe.

JavaScript: Take an index of an item in an array, and figure out what the index of the same item would be if the array were reversed?

The Setup
I have an array of objects called Elements. They are visually laid out like layers in a photoshop document. I have stripped out most of the data from each element for brevity. But the data changes for each element, because they are all different.
elements = [
{
name: 'First Piece',
},
{
name: 'Second',
},
{
name: 'Third',
},
{
name: 'Fourth', // is selected
},
{
name: 'Fifth',
},
]
I keep track of which element is selected in an object using the index of the selected item. I use the index because it is always available to me at any given time or place the elements are represented. The object looks like this, sans the non relevant data:
selected = {
element: 3,
}
This all works great.
The Problem
The problem lies in what could be considered my Layers panel. When the elements are on the 'canvas', they are in the correct order with each element having a higher z-index. But in the layers panel, I have to reverse the array so that it visually makes sense. So the 'Fifth' element is on top.
The problem is when I need to take the value of selected, and apply it to the reversed elements array.
elementsReversed = [
{
name: 'Fifth',
},
{
name: 'Fourth', // this should be selected
},
{
name: 'Third',
},
{
name: 'Second', // would be selected
},
{
name: 'First Piece',
},
]
I can't use .findIndex() because the names could be set to the same value (for a reason) and there aren't really other attributes I could use to search through a reversed array and find the index that way. I am trying to avoid adding another key/value pair to my objects like an ID.
Is there a way to do this? Am I just being a dum dum?
Thank you.

Javascript Map a Collection

The Issue:
I'm attempting to build a simple search tool. It returns a search query by matching an id to another item with the same id. Without going into the complexities, the issue I'm having is that when my data was organized previously, the map function from javascript returned all the results perfectly. However, now that my data is structured a bit differently (a collection, I think?) ....the ids don't appear to be lining up which causes the wrong search results to show.
The function in question:
const options = this.props.itemIds.map((id) => (
<Option key={this.props.itemSearchList[id].id}>
{this.props.itemSearchList[id].name}
</Option>
));
When the data was structured like this it worked as expected:
Example of previous structure:
const items = [
{
id: 0,
name: "name 0",
tags: ['#sports', '#outdoor', '#clothing'],
},
{
id: 1,
name: "name 1",
tags: ['#sports', '#outdoor', '#clothing'],
},
{
id: 2,
name: "Name 2",
tags: ['#sports', '#outdoor', '#clothing'],
},
Now that the data is a ?collection...the map function doesn't work as anticipated and it returns improper results or none at all: I've been able to use the lodash Map function on this structure successfully in the past.
Here's a screenshot of the new data:
I believe a representative way to write out the example would be:
const newItems = [
0: {
id: 0,
name: "name here",
},
1: {
id: 1,
name: "name here",
},
]
Any recommendations for making this work or need more info? Perhaps I'm misunderstanding the issue entirely, but I believe it has to do with data structure and the map function from JS. I can see results returning, but the id's are not lining up appropriately anymore.
Here's a visual representation of the misalignment. The orange is the search input and it pulling the right result. The green is the misalignment of what it's actually showing because of the data structure and mapping (I assume).
The issue is you were using index and lining that up with id as a sort of pseudo-key which is...beyond fragile. What you should be doing is keying by id (meaing itemsshould be an object) and then having a seperate array that stores the order you want. So items would be an object keyed by id:
const items = {
1: {
id: 1,
name: "name 1",
tags: ['#sports', '#outdoor', '#clothing'],
},
2: {
id: 2,
name: "name 2",
tags: ['#sports', '#outdoor', '#clothing'],
},
9: {
id: 9,
name: "Name 9",
tags: ['#sports', '#outdoor', '#clothing'],
},
};
And then itemIds (which it appears you already have) is an array with the correct order:
const itemIds = [1,9,2];
And then they can be accessed in the right order by looping over that array, and getting the element by said key:
itemIds.map((id) => {
const item = items[id];
// do something with the item
}
Take a look at how Redux recommends normalizing state shape.
https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape
What you call "collections" and "maps" are actually arrays. Now one of the arrays has the objects exactly at the position in the array that matches the id:
items[5].id === 5
Now through sorting /mutating / whatever you change the order so that the element at a certain position doesnt have that as an id:
newItems[5].id // 7 :(
That means that you cannot access the item that easy anymore, you now either have to sort the array again to bring it into order, or you search for an object with the id:
newItems.find(item => item.id === 5) // { id: 5, ... }
Or you switch over to some unsorted collections like a real Map:
const itemsMap = new Map(newItems.map(item => ([item.id, item])));
So you can get a certain item with its id as:
itemsMap.get(5) // { id: 5, ... }
... but the whole thing doesnt have to do with Array.prototype.map at all.
Here was my simple solution:
const options = [];
this.props.itemList.forEach((item) => {
if (this.props.searchResults.includes(item.id)) {
options.push(<Option key={item.id}>{item.name}</Option>);
}
});
Let me know what you think (to the group that tried to help!)

Is there a points-free way of filtering out tuples from a list by comparing their elements?

So I have some code which has a requirement of calling xprod with (input, input), similar to as follows:
const input = [
{ id: 1, data: 'a' },
{ id: 2, data: 'b' },
];
const product = xprod(input, input);
/*
[
[ { id: 1, data: 'a' }, { id: 1, data: 'a' } ],
[ { id: 1, data: 'a' }, { id: 2, data: 'b' } ],
[ { id: 2, data: 'b' }, { id: 1, data: 'a' } ],
[ { id: 2, data: 'b' }, { id: 2, data: 'b' } ],
]
*/
I'd like to filter tuples in the list above by comparing the first element of the tuples to the second element in the same tuple. In this case, to remove the tuples which contain objects which have equal ids (so the 0th and 3rd elems should be filtered out -- I know in this simplified example I could use strict equality to filter, too, but that's often not the case in the code I'm actually writing).
I know I can accomplish this pretty simply with lambdas, but since I find myself ending up with this sort of data (lists of tuples) fairly often when working with ramda, I often get stuck on trying to compare one item in a tuple to another item in the same tuple in a points free manner. And maybe that's an argument to just keep it simple and use the lambda, but I'm curious if there's a different way to do it.
Here's a link to a ramda repl containing an implementation.
One option is to simply wrap a function that expects the two arguments of the tuple with R.apply. In your example that could be a partially applied R.eqProps.
R.filter(R.apply(R.eqProps('id')), product)

Efficient algorithm / recursive function to nest items from a list

I'm currently implementing my own commenting system. Unfortunately Disqus or any other comment platform doesn't meet my requirements.
I use NodeJS and MongoDB as backend. I need to run basically two queries on my database:
Get all comments by a topic/slug
Get all comments by a user
One can comment to an topic or reply to a comment.
Hey, cool post # top lvl comment
Thanks! # reply to comment
Foo Bar! # reply to reply
and so on...
So my database schema looks like
{
id: ObjectId,
text: string,
author: { id: ObjectId, name: string },
parent: nullable ObjectId,
slug: string/number/whatever
}
If parent is null it's a top level comment, otherwise it's a reply.
Pretty easy so far, right? The problem I do have now is displaying comments below posts. When there would be only top level comments it would be easy. Just get all comments for one specific slug, sort them by date/rating/... and compile them with my HTML View Engine.
But there are in fact replies and I'm just stuck at the point where I need to organize my structure. I want to nest replies into comments within my list
Original list (simplified)
[
{ id: 1, text: 'foo', parent: null },
{ id: 2, text: 'bar', parent: 1 },
// ...
]
Expected Output
[
{ id: 1, text: 'foo', replies: [
{ id: 2, text: 'bar' },
] },
]
I've tried creating my expected output with a recursive function which got very weird tho. Unless that it wouldn't be very efficient. So since I'm really getting frustrated and kinda feeling stupid not solving this problem I've decided to ask for your help SO.
The actual problem I want to solve: How do I render my comments, that they are properly nested etc.
The question I'm going to ask: How do I organize my flat structure in an efficient way to solve the above described problem?
Here's one approach with linear complexity:
var comments = [{
id: 3,
text: 'second',
parent: 1
}, {
id: 1,
text: 'root',
parent: null
}, {
id: 2,
text: 'first',
parent: 1
}, {
id: 5,
text: 'another first',
parent: 4
}, {
id: 4,
text: 'another root',
parent: null
}];
var nodes = {};
//insert artificial root node
nodes[-1] = {
text: 'Fake root',
replies: []
};
//index nodes by their id
comments.forEach(function(item) {
if (item.parent == null) {
item.parent = -1;
}
nodes[item.id] = item;
item.replies = [];
});
//put items into parent replies
comments.forEach(function(item) {
var parent = nodes[item.parent];
parent.replies.push(item);
});
//root node replies are top level comments
console.log(nodes[-1].replies);

Categories

Resources