Sorting an array which contains string object in react - arrays

I'm retrieving the data from the radio button checked for database purposes and I wanted to check the string objects index are equal to the api response string object from the db. The user can select the radio button in any order, but finally I wanted to sort the radio button with respect to get api response
Since, I'm new to react, I am trying to start off with...
I have attached the response below
data:
matrix:
option_questions: Array(10)
0: {text: "Hai"}
1: {text: "Hello"}
2: {text: "Hola"}
options: Array(10)
0: {text: "1"}
1: {text: "2"}
2: {text: "3"}
After checking the radio button values, my array goes likes this...
0:
id: "3"
qn: "Hello"
1:
id: "1"
qn: "Hola"
2:
id: "2"
qn: "Hai"
Here, I have to rearrange the array using the qn object index only like below format..
0:
id: "2"
qn: "Hai"
1:
id: "3"
qn: "Hello"
2:
id: "1"
qn: "Hola"
This is my code for on change
changeRadioHandler = (event) => {
const qn = event.target.name;
const id = event.target.value;
const question = {
id: event.target.value,
qn
};
if (this.state.questions.some((question) => question.qn === qn)) {
questions = [
...this.state.questions.filter((question) => question.qn !== qn),
question,
];
} else {
questions = [...this.state.questions, question];
}
const comparator = (a, b) => a.qn.localCompare(b.qn);
console.log(questions.sort(comparator), "comparator");
questions.sort(comparator);
this.setState({ questions });
console.log(questions);
};

Create a comparator function to compare the qn properties of each element and do a localeCompare comparison.
const comparator = (a, b) => a.qn.localeCompare(b.qn);
const data = [
{
id: "3",
qn: "Hello"
},
{
id: "1",
qn: "Hola"
},
{
id: "2",
qn: "Hai"
},
];
const comparator = (a, b) => a.qn.localeCompare(b.qn);
console.log(data.sort(comparator));

Related

React native: how to find an item in array?

i have this array:
var arr = [{"3": "2"}, {"2": "6"}, {"4": "7"}, {"5": "9"}];
I cant get the value by index, i am trying to do this:
console.log(arr[3]); //output needed: 2.
console.log(arr[5]); //output needed: 9.
...
any help please?
UPDATE:
I am trying to add sub categories to an array with the main category:
const [subcatsSelectedForNow,setSubCatsSelectedForNow]=useState([]);
const selectCat = (catid,maincat)=>{
var arr=subcatsSelectedForNow || [];
arr.push({
[catid]:maincat
});
setSubCatsSelectedForNow(arr);
};
const arr = [{ 3: "2" }, { 2: "6" }, { 4: "7" }, { 5: "9" }];
You simply can't achieve your accepted behavior using console.log(arr[3]);
First you need to find whether the property(catid) exist in the array or not & if it is exist then you can get the object value as below,
const find = (num) => {
let obj = arr.find((item) => item[num]);
return obj && obj[num];
};
console.log(find(3)); //Output -> 2
Hope this helps you. Feel free for doubts.

Insert list data over the iteration(map)

Here I am trying to modify my data over the iteration and send some result to API call.
The API Call receives a request with a structured data format which is
{ list: [{ id: "1", name: "Hello" }, ... ] }
Somehow I managed to call the API with single data ( const params in my current code, it only accepts single data).
But now it has to be done with multiple data something like this:
{ list: [{ id: "1", name: "Hello" }, { id: "22", name: "Ed" }, { id: "36", name: "Jason" } ... ] }
Here is my current code
const [table, setTalbe] = useState(..); // assume, we have some table data here
const processNow = () => {
let id = 0;
let name = '';
// if table length is greater than 1, we go for the loop.
if (table.length >= 1) {
table.map(data => {
id = data.userId;
name = data.userName;
});
//insert table data to params, here I want to add whole table data into "list"
//the final result of this list should be something like this
//ex ) list: [{ id: '123', name: 'Josh' }, { id: '125', name: 'Sue' }, { id: '2222', name: 'Paker' } ...],
// but how??
const params: any = {
list: [
{
id: id,
name: name
},
],
};
//send PUT reqeust with params
axios
.put(
'/api/v1/tosent',
params,
)
.then(res => {
console.log('The response', res);
})
.catch(err => {
console.log('The error: ', err);
});
}
};
but I'm stuck with it, please help me to finish this code to work properly.
need your kind advice.
Array.prototype.map returns a new array with the function you pass applied to every element. You should study the MDN documentation on map to understand its use.
Your current code does nothing with the map return value:
table.map(data => {
id = data.userId;
name = data.userName;
});
You probably assumed .map would mutate the data, as in change it in place. Instead, the whole operation returns a new array.
It looks like you want to do:
const list = table.map(data => {
return {
id: data.userId,
name: data.userName
}
});
This is applying a function to every element in the array that will map each element to a new object, matching your question, with an id and name key. Then it looks like you want to pass the returned value of map (which we named list above) to your call:
const params: any = {
list: list
};

Trying to filter strings in list in Reactjs

This code works, but NOT as expected. For example, typing: red displays "Red Hot Chili Peppers", but continuing with red hot, and it disappears. I am not sure, how a new RegExp should be applied in this code. I managed to come this far with the filtering.
query = "red hot";
const matches = [
"Red Hot Chili Peppers",
"Dua Lipa",
"X&Y",
"Viva la Vida or Death and All His Friends"
];
const lowercasedFilter = query.toLowerCase();
const filtered = matches.filter(item => {
return Object.keys(item).some(key =>
typeof item[key] === "string" && item[key].toLowerCase().includes(lowercasedFilter)
)
});
EDIT: I am sorry, my bad. I have a list of objects.
An object:
0: {…}
external_urls: Object { spotify: "https://open.spotify.com/artist/0L8ExT028jH3ddEcZwqJJ5" }
followers: Object { href: null, total: 14620829 }
genres: Array(5) [ "alternative rock", "funk metal", "funk rock", … ]
href: "https://api.spotify.com/v1/artists/0L8ExT028jH3ddEcZwqJJ5"
id: "0L8ExT028jH3ddEcZwqJJ5"
images: Array(3) [ {…}, {…}, {…} ]
name: "Red Hot Chili Peppers" ​​
popularity: 86 ​​
type: "artist"
uri: "spotify:artist:0L8ExT028jH3ddEcZwqJJ5"
<prototype>: Object { … }
EDIT: This comes close, but doesn't work as expected:
const filtered = matches.filter(match => {
const regex = new RegExp(`^${query}`, 'gi');
return match.name.match(regex);
});
Doesn't work: red hot chili peppers.
As commented:
No need for this: Object.keys(item) and item[key] === "string" as its an array of string
Your structure is an array of string. So you can directly consume the value and use String methods to validate it
If you have a complex data structure, like nested objects, then using Object.keys and then looping on them makes more sense as you do not know what keys you might need.
const query = "red hot";
const matches = [
"Red Hot Chili Peppers",
"Dua Lipa",
"X&Y",
"Viva la Vida or Death and All His Friends"
];
const filteredList = matches
.filter((match) => match.toLowerCase().includes(query))
console.log(filteredList)
You can even use Regex for this. This will allow you to ignore toLowerCase() call for every iteration
var list = [{
external_urls: {
spotify: "https://open.spotify.com/artist/0L8ExT028jH3ddEcZwqJJ5"
},
followers: {
href: null,
total: 14620829
},
genres: ["alternative rock", "funk metal", "funk rock"],
href: "https://api.spotify.com/v1/artists/0L8ExT028jH3ddEcZwqJJ5",
id: "0L8ExT028jH3ddEcZwqJJ5",
name: "Red Hot Chili Peppers",
popularity: 86,
type: "artist",
uri: "spotify:artist:0L8ExT028jH3ddEcZwqJJ5"
}]
const query = 'red hot'
const regex = new RegExp(query, 'gi')
const filteredList = list
.filter((item) => regex.test(item.name))
console.log(filteredList)

How to find objects with the same property values in an Array of Objects in typescript?

I have an array of objects
var myArray = [
{id: 1, name: 'Foo Bar', email: 'foo#bar.com'},
{id: 2, name: 'Bar Foo', email: 'bar#foo.com'},
{id: 3, name: 'Joe Ocean', email: 'joe#ocean.com'},
{id: 3, name: 'Jenny Block', email: 'foo#bar.com'},
];
I am expecting the following output:
commonIdsObjects = [
{id: 3, name: 'Joe Ocean', email: 'joe#ocean.com'},
{id: 3, name: 'Jenny Block', email: 'foo#bar.com'},
]
I assume that you want the output to be a single array containing all the duplicate entries, even if some of those entries have different ids. For example, if you had added {id: 2, name: 'Fishy Joe', email: 'com#foo.bar'} to myArray, the resulting commonIdsObjects would be an array of four items: two for id: 2 and two for id: 3. If this is not what you want then you should take care to specify exactly the expected behavior.
Anyway, assuming you have a type corresponding to the elements of myArray, like this:
type Elem = typeof myArray[number];
And assuming your target runtime has access to the Object.values() and Array.prototype.flat() methods, then you can write
const commonIdsObjects = Object.values(
myArray.reduce<{ [k: number]: Elem[] }>(
(a, v) => ((a[v.id] || (a[v.id] = [])).push(v), a), {}
)
).filter(c => c.length > 1).flat(1);
What we're doing is using myArray.reduce() to build an object whose keys correspond to your elements' id values, and whose values are arrays of elements with those id. We convert this object into an array of arrays of elements, keep only those whose lengths are more than one (i.e., any id with more than one element corresponding to it), and flatten into a single array.
This will produce the desired result:
console.log(JSON.stringify(commonIdsObjects));
// [{"id":3,"name":"Joe Ocean","email":"joe#ocean.com"},
// {"id":3,"name":"Jenny Block","email":"foo#bar.com"}]
If you don't have access to Object.values() and [].flat() you can use Object.keys() and [].reduce() instead:
type ElemsById = { [k: string]: Elem[] }
const commonIdsObjects2 = ((o: ElemsById) => Object.keys(o).map(k => o[k]))(
myArray.reduce<ElemsById>(
(a, v) => ((a[v.id] || (a[v.id] = [])).push(v), a), {}))
.filter(c => c.length > 1).reduce<Elem[]>((a, v) => (a.push(...v), a), []);
console.log(JSON.stringify(commonIdsObjects2)); // same
which is essentially the same algorithm. Or you could do this algorithm the purely-imperative-programming way with various for loops:
const elemsById: ElemsById = {};
for (let v of myArray) {
if (!elemsById[v.id]) {
elemsById[v.id] = []
}
elemsById[v.id].push(v);
}
const commonIdsObjects3: Elem[] = []
for (let k in elemsById) {
if (elemsById[k].length <= 1) {
continue;
}
for (let v of elemsById[k]) {
commonIdsObjects3.push(v);
}
}
console.log(JSON.stringify(commonIdsObjects3)); // same
Okay, hope that helps; good luck!
Playground link to code
var myArray = [
{ id: 1, name: "Foo Bar", email: "foo#bar.com" },
{ id: 2, name: "Bar Foo", email: "bar#foo.com" },
{ id: 3, name: "Joe Ocean", email: "joe#ocean.com" },
{ id: 3, name: "Jenny Block", email: "foo#bar.com" }];
const commonIdsObjects = myArray.filter(x => x.id === 3);
console.log(commonIdsObjects);

How to remove the right element from array react?

I want to remove an element from my array when click on a specific row.
When I click on an element it does nothing or the last row gets deleted.
I tried to remove the element like this:
ondeleterow(e: any) {
const array = [...this.state.fields.columns]; // make a separate copy of the array
const index = array.indexOf(e.target.id);
if (index !== -1) {
array.splice(index, 1);
this.setState({ fields: { columns: array }});
}
}
My array/json object looks like this:
[ {index: 0, name: "person 1", age: 12},
{index: 1, name: "person 2", age: 19},
{index: 2, name: "person 3", age: 34},
]
My result should be when I click on a row with ID=1 the row with index: 1 gets deleted from my state array.
I can't give them an Id because when I submit the json structure then does not get accepted.
I feel like your Array.splice might be causing the issue here (because even though you created a new array, the objects in the array are still passed by reference).
I would recommend a completely different method of doing this operation which I've found to be far cleaner and robust.
First you have to add a unique id field to each row. (this is good practice in react anyway, instead of using index for keys).
ondeleterow(id: string) {
return (e: any) => {
const array = this.state.fields.column.filter(item => item.id != id)
this.setState({ fields: { columns: array }});
}
}
and when you're mapping over your rows, you can simply add the function to the onClick like this
<Row key={item.id} onClick={ondeleterow(item.id)} />
Never use splice in react especially with state. They directly mutate the data. Use non mutating operations like slice.
Your code should as follows
ondeleterow(e: any) {
const array = [...this.state.fields.columns]; // make a separate copy of the array
const index = array.indexOf(e.target.id);
if (index !== -1) {
array.splice(index, 1);
this.setState({ fields: {
columns: [ ...array.slice(0, index), ...array.slice(index + 1, array.length) ]
}});
}
}
You can use Array.filter. This will allow you to create a new array with only the items you want based on a certain criteria. In this case, you want an array with items that have a different ID that the one you want to remove. So it will look like this
// Actual processing
const filterByIndex = (arr, idx) => arr.filter(x => x.index !== idx);
// Your data
const json = [{
index: 0,
name: "person 1",
age: 12
},
{
index: 1,
name: "person 2",
age: 19
},
{
index: 2,
name: "person 3",
age: 34
},
];
// Printing the result
console.log(filterByIndex(json, 1));
In your React app
ondeleterow(e: any) {
const columns = this.state.fields.columns.filter(x => x.index !== e.target.id);
this.setState({ fields: { columns }});
}
Try this
onDeleteRow(e) {
const afterRemoval = this.setState.fields.columns.filter(item => item.index != e.target.id);
this.setState(prevState => ({ fields: { ...prevState.fields, columns: afterRemoval } }));
}
The other solution above sets the fields field directly, It may work but will cause problem if fields has some other attribute other than columns (those attributes will get removed)

Resources