ES6 filter an array of objects retrieving a field that is an empty array or does not contain certain value - ecmascript-6

I am trying to filter the following array
const matches = [
{
"match": "1",
"teams": [
[
{ "name": "david"},
{ "name": "tom"}
],
[
{ "name": "liam"},
{ "name": "noah"}
]
]
},
{
"match": "2",
"teams": [
[
{ "name": "david"},
{ "name": "tom"}
],
[
{ "name": "oliver"},
{ "name": "elijah"}
]
]
},
{
"match": "3",
"teams": []
}
]
I want to retrieve the objects where the teams array is empty, or "oliver" does not belong to the teams. It should retrieve match "1" and "3"
I tried the following
matches.filter(match => match.teams.length === 0 || !match.teams.includes({ name: "oliver" })
matches.filter(match => match.teams.length === 0 || !match.teams.some(team => team.name === "oliver" })
but I am getting the 3 objects

match.teams is an array of arrays of players
try this
matches.filter(match =>
match.teams.length === 0 ||
match.teams.every(team =>
team.every(player => player.name !== "oliver" )
)
)

// use array.flat method. teams is arrays of arrays
const result=matches.filter(match=>{
if(!match.teams.length){
return true;
}
const teamArray=match.teams.flat(1);
console.log(teamArray);
const search=teamArray.find(player=>player.name!=="oliver");
if(search){
return true;
}
return false;
});

Related

Sort values of Observable array of objects

My service get data from Api :
async getCommunes(){
return await this._http.get<any[]>(this.api)
.pipe()
.toPromise()
.then((response: any) => {
this._communes$.next(response);
})
.catch(err => console.log(err))
}
I call service in a component :
public communes$: Observable<any>;
constructor(private apiService: ApiService) { }
ngOnInit(): void {
this.loadCommunes();
}
get communesFromService$(){
return this.apiService.communes$;
}
async loadCommunes(){
await this.apiService.getCommunes();
this.communes$ = this.apiService.communes$;
}
I display data in Html by calling communesFrom Service$ (get method) :
<div *ngFor="let record of (communes$ | async)?.records">{{record?.fields?.name}}</div>
My data are formated like below :
{
"nhits": 38,
"parameters": {
"dataset": "communes-de-la-province-de-namur",
"rows": 3,
"start": 0,
"format": "json",
"timezone": "UTC"
},
"records": [
{
"datasetid": "communes-de-la-province-de-namur",
"recordid": "5f50799324d15038c9708e48c6a32c907922d00a",
"fields": {
"nsi": "93088",
"geo_shape": {
"coordinates": [
[
[
4.516510705656462,
50.31531488802985
]
]
],
"type": "Polygon"
},
"geo_point_2d": [
50.26709679846407,
4.433557385138468
],
"name": "Walcourt"
},
"geometry": {
"type": "Point",
"coordinates": [
4.433557385138468,
50.26709679846407
]
},
"record_timestamp": "2019-02-13T15:00:55.334000+00:00"
},
{
"datasetid": "communes-de-la-province-de-namur",
"recordid": "11fc2dbd6852c06f095e71adee7e0c1d334ccf24",
"fields": {
"nsi": "91054",
"geo_shape": {
"coordinates": [
[
[
4.971517147861946,
50.02965137853804
]
]
],
"type": "Polygon"
},
"geo_point_2d": [
49.98493619689069,
4.901523112944346
],
"name": "Gedinne"
},
"geometry": {
"type": "Point",
"coordinates": [
4.901523112944346,
49.98493619689069
]
},
"record_timestamp": "2019-02-13T15:00:55.334000+00:00"
},
{
"datasetid": "communes-de-la-province-de-namur",
"recordid": "82a588f6f7d3250b78564fd7a1f16c0a02d0e30a",
"fields": {
"nsi": "92045",
"geo_shape": {
"coordinates": [
[
[
4.827793680052161,
50.41154443216362
]
]
],
"type": "Polygon"
},
"geo_point_2d": [
50.435523543496686,
4.754395027090274
],
"name": "Floreffe"
},
"geometry": {
"type": "Point",
"coordinates": [
4.754395027090274,
50.435523543496686
]
},
"record_timestamp": "2019-02-13T15:00:55.334000+00:00"
}
]
}
I only need 'name' field but order by ascending ('records' array).
I have tried this but it doesn't work. I also tried other solution but without success.:
get communesFromService$(){
return this.apiService.communes$.pipe(
map((response => response.sort((a,b) => a.name - b.name)))
);
}
How can I do that?
any suggestions is helpfull.
Thanks
JavaScript arrays have a sort( ) method that sorts the array items into alphabetical order.
You can only get the name property out of all the values and sort it and then return it from service. Like below:-
Service Method:-
getNames(): Observable<string[]> {
return this.http.get(`API url`).pipe(
map((x:any) => x.records.map((item) => item.fields.name).sort())
);
}
Component: Just assign the method to an observable:-
export class AppComponent {
name$ = this.dataService.getNames();
constructor(private dataService: DataService) {}
}
In Component, template use the async pipe:-
<div *ngIf="(name$ | async) as result">
<ul>
<li *ngFor="let item of result">{{item}}</li>
</ul>
</div>
Demo with sample data:-
https://codesandbox.io/s/optimistic-tdd-dm898?file=/src/app/app.component.html
Update :-
if you have non-English alphabets in your string consider the below method for sorting.
getNames(): Observable<string[]> {
return of(APIReponse).pipe(
map((x) => x.records.map((item) => item.fields.name).sort((a, b) => {
return a.localeCompare(b, 'en', { sensitivity: 'base' });
}))
);
}
You can use just-sort-by - which is a very light library.
npm install just-sort-by
If your array is what is returned from the API call, then:
import sortBy from 'just-sort-by';
get communesFromService$(){
return this.apiService.communes$.pipe(
map((response) => sortBy(response, (item) => item.fields.name))
);
}

How to pass an array into laravel json?

Here my simple code..
$country=['Bangladesh','Pakistan'];
$capital=['Dhaka','Islamabad'];
return response()->json([
'country'=>$country,
'roll'=>$roll,
]);
If i run the above code ,the output will be like below..
{
"country": [
"Bangladesh",
"Pakistan"
],
"roll": [
'Dhaka',
'Islamabad'
]
}
But I want that my expected output will be like ..
EDIT: Following JSON is invalid (2 same key country)
{
{
"country":"Bangladesh",
"capital":"Dhaka"
},
{
"country":"Pakistan",
"capital":"Islamabad"
},
}
try this
$countries = ['India', 'Bangladesh', 'Pakistan'];
$capital = ['Delhi', 'Dhaka', 'Islamabad'];
$response = [];
foreach ($countries as $key => $country) {
$response[$key] = [
'country' => $country,
'capital' => $capital[$key],
];
}
return response()->json($response);
it will return
[{
"country": "India",
"capital": "Delhi"
},
{
"country": "Bangladesh",
"capital": "Dhaka"
},
{
"country": "Pakistan",
"capital": "Islamabad"
}
]
Your expected output is wrong. You simply cant have 2 same keys (country) in output json. You should have country and capital encapsulated in separate {}.

How to store json data based on another field data in different arrays

I have a json array like this.
[
{
"id": "1",
"date": "2020-02-21",
"status": "present",
"studentid": "1"
},
{
"id": "2",
"date": "2020-02-24",
"status": "present",
"studentid": "1"
},
{
"id": "3",
"date": "2020-02-25",
"status": "absent",
"studentid": "1"
},
{
"id": "4",
"date": "2020-02-26",
"status": "absent",
"studentid": "1"
}
]
I can store the date by using this code snippet
if (data instanceof Array) {
this.date=data.map(ele => ele.date);
}
How to store the dates in two arrays based on absent and present conditions.That is i want to store date_present in one array and date_absent in another array.
Using Map function to iterate and check the status of each element
var present = [];
var absent = [];
data.map(ele => {
ele.status === "absent" ? absent.push(ele) : present.push(ele);
});
Use forEach to loop through the array and push the object to separate arrays
var date_present = [];
var date_absent = [];
data.forEach(ele => {
if(ele.status === "present"){
date_present.push(ele)
}
else if(ele.status === "absent"){
date_absent.push(ele)
}
});
Try like this:
var date_present = [];
var date_absent = [];
date_present = data.filter(item => item.status === "present")
date_absent = data.filter(item => item.status === "absent")

react native json image

I want to print out JSON images as a variable.
This is my local JSON file (JsonData.json):
{
"appetizer": [
{
"num": "appetizer1",
"name": "salad",
"condition": [ "1", "2" ],
"image": "./appetizer/salad.png"
},
{
"num": "appetizer2",
"name": "soup",
"condition": [ "2", "3" ],
"image": "./appetizer/soup.png"
},
…
],
"main": [
{
"num": "main1",
"name": "beef",
"condition": [ "1" ],
"image": "./main/beef.png"
},
{
"num": "main2",
"name": "fish",
"condition": [ "2", "3" ],
"image": "./main/fish.png"
},
…
]
}
I filtered the name when condition="2". (salad,soup,fish)
This is the code for filtering name:
const newArray1 = [...JsonData["apptizer"], ...JsonData["main"]];
const JsonResult = newArray1.filter(item => {
if(item.condition.indexOf("2") !== -1) return item.name;
});
AND I want to get the image when condition="2".
How can I get them? And How can I print out them?
Do I have to use base64? If so, Can you tell me how to use it?
I saw the explanation, but I can't understand it.
And I imported JSON file this way (I've been correctly using it):
var JsonData = require('./JsonData.json');
You can use below code:
let mainObject = JSON.parse(JSON.stringify(data))
let allKeys = Object.keys(mainObject)
let finalObject = []
allKeys.map((value, index) => {
let array = mainObject[value]
array.map((aryObject, aryIndex) => {
let condition = aryObject['condition']
if (condition.includes('2')) {
finalObject.push(aryObject)
}
})
})
alert(JSON.stringify(finalObject))
You can import data in top of screen:
import { data } from './data';
You can add below text in data.js:
export const data = {
"appetizer": [
{
"num": "appetizer1",
"name": "salad",
"condition": ["1"],
"image": "./appetizer/salad.png"
},
{
"num": "appetizer2222",
"name": "soup",
"condition": ["2", "3"],
"image": "./appetizer/soup.png"
},
],
"main": [
{
"num": "main1",
"name": "beef",
"condition": ["1"],
"image": "./main/beef.png"
},
{
"num": "main2",
"name": "fish",
"condition": ["21", "3"],
"image": "./main/fish.png"
},
]
}
You can use Object#values to get the arrays corresponding to appetizer and main and then Array#flat to extract the nested objects into a transformed array. Then use the Array#filter (which you are already using) to filter out only the required objects based on your condition and then Array#map to get the name and image values out of every filtered object into an array of objects.
Please consider following snippts
const jsonData = {"appetizer":[{"num":"appetizer1","name":"salad","condition":["1","2"],"image":"./appetizer/salad.png"},{"num":"appetizer2","name":"soup","condition":["2","3"],"image":"./appetizer/soup.png"}],"main":[{"num":"main1","name":"beef","condition":["1"],"image":"./main/beef.png"},{"num":"main2","name":"fish","condition":["2","3"],"image":"./main/fish.png"}]};
const filteredValues = Object.values(jsonData)
.flat()
.filter(o => o.condition.includes('2'))
.map(({name, image}) => ({ name, image }));
console.log(filteredValues);
The output of the above code will be an array of objects having the following structure
[{
"name": SOME_NAME,
"image": SOME_PATH
},
{
"name": SOME_NAME,
"image": SOME_PATH
},
...
]
You can use the above array to retrieve your image path and display it accordingly.
I think you shouldn't be worried about base64 as images are stored locally and path will be sufficient to display the image.
Hope this will help!!!
Side Note: You can avoid the Array#flat part as you are already doing it manually [...JsonData["apptizer"], ...JsonData["main"]] but flat will be handy in case there are more keys in jsonData that need to be considered.

Any smart JSON/JS Object counting packages?

I don't mean to be duplicating any questions, since I have read so many great answers here on StackOverflow.
Given the below JSON data:
[
{
“department”: “vice”,
“team”: [
{
"selected": "Yes"
},
{
“selected": “No”
}
],
“fund”: [
“team_a”
“team_c”
]
}
]
I want to return a count of selected, so from the above 'yes'=1 and 'no'=1.
I understand I can do it through for loop, using a simple countYes++ to return the answer, however I have 2 questions as below:
Is there any other way (i.e. using some npm package).
In my example the options are simple Yes and No, if I have a bigger list of things to count, how to count all unique ones > 0?
Thanks.
I tried to write using vanilla JS you can look for library like underscore, lodash for more options.
var data = [
{
"department": "vice",
"team": [
{
"selected": "Yes"
},
{
"selected": "No"
}
],
"fund": [
"team_a",
"team_c"
]
},
{
"department": "vice",
"team": [
{
"selected": "Yes"
},
{
"selected": "Yes"
}
],
"fund": [
"team_a",
"team_c"
]
},
{
"department": "vice",
"team": [
{
"selected": "Yes"
},
{
"selected": "No"
}
],
"fund": [
"team_a",
"team_c"
]
}
];
function decisionReducer(prev, next) {
var team = next.team;
if (team && Array.isArray(team)) {
team.forEach(function (row) {
if (row.selected === 'Yes') {
prev.yes += 1;
}
if (row.selected === 'No') {
prev.no += 1;
}
})
}
return prev;
};
var counter = data.reduce(decisionReducer, {yes: 0, no: 0})
console.log(counter);