Convert arrays of active days to readable string - javascript

I need to convert an array of boolean values indicating whether the store is open on a given day.
For example:
Case 1:
Input data: [true, true, true, true, true, true, true]
Expected output: Every day
Case 2:
Input data: [true, true, true, true, true, false, false]
Expected output: Mon-Fri
Case 3:
Input data: [true, true, false, false, true, true, true]
Expected output: Mon-Tue, Fri-Sun
Case 4:
Input data: [true, false, false, true, false, false, true]
Expected output: Mon, Thu, Sun
Case 5:
Input data: [true, true, false, true, true, true, false]
Expected output: Mon-Tue, Thu-Sat
Case 6:
Input data: [true, false, false, false, false, false, false]
Expected output: Only Monday
I came up with this, but need help with cases 2-5
const daysLabels = [
{ label: "Monday", short: "Mon" },
{ label: "Tuesday", short: "Tue" },
{ label: "Wednesday", short: "Wed" },
{ label: "Thursday", short: "Thu" },
{ label: "Friday", short: "Fri" },
{ label: "Saturday", short: "Sat" },
{ label: "Sunday", short: "Sun" }
];
const getSchedule = ({ case: days }) => {
let activeDays = [];
for (let i = 0; i < [...days].length; i++) {
const day = [...days][i];
if (day) {
activeDays.push({ ...daysLabels[i], value: day });
}
}
if (activeDays.length === 7) {
return "Every day";
}
if (activeDays.length === 1) {
return `Only ${activeDays[0].label}`;
}
return "#TODO";
};
Sandbox - link

Here's my answer, This is not an optimized version.
Add below function:-
function getWeekDuration(cases) {
let index = 0;
let weekDurationArray = [];
for (let i = 0; i < cases.length; i++) {
const day = cases[i];
if (i === 0) {
weekDurationArray[index] = [];
}
if (day) {
weekDurationArray[index].push({ ...daysLabels[i],
value: day
});
} else {
if (weekDurationArray[index].length > 0) {
index += 1;
weekDurationArray[index] = [];
}
}
}
// remove empty arrays
weekDurationArray = weekDurationArray.filter(item => item.length > 0);
// get only first and last day of each week duration
weekDurationArray = weekDurationArray.map(weekDuration => {
// concate inner array into string
if (weekDuration.length > 1) {
return `${weekDuration[0].short}-${weekDuration[weekDuration.length - 1].short}`;
}
return weekDuration[0].short;
});
return weekDurationArray.join(', ');
}
Add return the function from getSchedule
return getWeekDuration(days);

You can use Array.reduce() to create groups of day ranges, along with the correct labels.
We then use a Array.map() call to return only the label for each range.
I've added the 6 test cases mentioned, they should all pass.
const daysLabels = [
{ label: "Monday", short: "Mon" },
{ label: "Tuesday", short: "Tue" },
{ label: "Wednesday", short: "Wed" },
{ label: "Thursday", short: "Thu" },
{ label: "Friday", short: "Fri" },
{ label: "Saturday", short: "Sat" },
{ label: "Sunday", short: "Sun" }
];
function getDayRange(input) {
// Deal with 7 days and 1 day only first...
if (input.filter(active => active).length === 7) {
return 'Every day';
} else if (input.filter(active => active).length === 1) {
return `Only ${daysLabels[input.findIndex(active => active)].label}`;
}
// 2 - 6 days active
return input.reduce((acc, active, idx) => {
if (active) {
if (!acc.length || acc[acc.length - 1].end < (idx - 1) ) {
acc.push({ start: idx, end: idx, label: daysLabels[idx].short, startLabel: daysLabels[idx].short });
} else {
acc[acc.length - 1].end = idx;
acc[acc.length - 1].label = acc[acc.length - 1].startLabel + '-' + daysLabels[idx].short;
}
}
return acc;
}, []).map(r => r.label).join(', ');
}
const cases = [
{ input: [true, true, true, true, true, true, true], expected: 'Every day' },
{ input: [true, true, true, true, true, false, false], expected: 'Mon-Fri' },
{ input: [true, true, false, false, true, true, true], expected: 'Mon-Tue, Fri-Sun' },
{ input: [true, false, false, true, false, false, true], expected: 'Mon, Thu, Sun' },
{ input: [true, true, false, true, true, true, false], expected: 'Mon-Tue, Thu-Sat' },
{ input: [true, false, false, false, false, false, false], expected: 'Only Monday' },
]
console.log(`Case`, '\t', 'Pass', '\t', 'Output')
cases.forEach(({ input, expected }, idx) => {
let output = getDayRange(input);
console.log(`${idx + 1}`, '\t', output === expected, '\t', output)
})
.as-console-wrapper { max-height: 100% !important; }

I declare a mapping array for the text, below is the example code,and you can modify the text when function return only one day or everyday.
// for index mapping
let indexMapping = [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun"
];
function getWeeks(arr){
let list = [];
let indexes = [];
let item = [];
// get all indexes
arr.forEach((result,index) => {
if(result) indexes.push(index);
});
// push each text to list
indexes.map(i => {
if(!indexes.includes(i-1)){
if(item.length == 1){
list.push(item[0]);
item = [];
}
item.push(indexMapping[i]);
}
else if(!indexes.includes(i+1)){
item.push(indexMapping[i]);
list.push(item.join("-"));
item = [];
}
});
// if indexes only has one item
if(item.length == 1){
list.push(item[0]);
}
return list;
}
// for test
let testArr2 = [true, true, true, true, true, false, false];
let testArr3 = [true, true, false, false, true, true, true];
let testArr4 = [true, false, false, true, false, false, true];
let testArr5 = [true, true, false, true, true, true, false];
getWeeks(testArr2); // output will be like ['Mon-Fri']

Use of Array#map with regular expressions may help have less hard-coding as follows:
const daysLabels = [
{ label: "Monday", short: "Mon" },
{ label: "Tuesday", short: "Tue" },
{ label: "Wednesday", short: "Wed" },
{ label: "Thursday", short: "Thu" },
{ label: "Friday", short: "Fri" },
{ label: "Saturday", short: "Sat" },
{ label: "Sunday", short: "Sun" }
],
getSchedule = ({ case: days }) => {
const out = days.map((b,i) => b ? daysLabels[i].short : ":")
.join(",").replace(/(?<![:\b]),[,A-za-z]*,(?![:\b])/g,"-")
.replace(/(?<=[a-z]),(?=[A-Z])/g,"-")
.replace(/[,\:]+/g,",").replace(/^[^A-Z]+|[^a-z]+$/g,"")
.replace(/,/g,", ");
return out === 'Mon-Sun' ? 'Every day' :
!out.match(/[\-,]/) ?
`Only ${daysLabels.find(({short}) => short === out).label}` :
out;
};
const cases = [
{ input: [true, true, true, true, true, true, true], expected: 'Every day' },
{ input: [true, true, true, true, true, false, false], expected: 'Mon-Fri' },
{ input: [true, true, false, false, true, true, true], expected: 'Mon-Tue, Fri-Sun' },
{ input: [true, false, false, true, false, false, true], expected: 'Mon, Thu, Sun' },
{ input: [true, true, false, true, true, true, false], expected: 'Mon-Tue, Thu-Sat' },
{ input: [true, false, false, false, false, false, false], expected: 'Only Monday' },
{ input: [false, false, false, true, false, false, false], expected: 'Only Thursday' },
{ input: [false, false, false, false, false, false, true], expected: 'Only Sunday' }
]
console.log(`Case`, '\t', 'Pass', '\t', 'Output')
cases.forEach(({ input, expected }, idx) => {
let output = getSchedule({case:input});
console.log(`${idx + 1}`, '\t', output === expected, '\t', output)
});
.as-console-wrapper { max-height: 100% !important; }

Related

How can update values in an array of objects?

how to get new array newSelect using map ,forEach
const selects = [false, true, true, true, false];
const oldSelects = [
{ select: true, name: 'AA' },
{ select: true, name: 'AA' },
{ select: true, name: 'AA' },
{ select: true, name: 'AA' },
{ select: true, name: 'AA' },
];
const newSelect = [
{ select: false, name: 'AA' },
{ select: true, name: 'AA' },
{ select: true, name: 'AA' },
{ select: true, name: 'AA' },
{ select: false, name: 'AA' },
];
oldSelects[0].select === selects[0]
#Inder answer is great, but a map looks more clean imo:
const selects = [false, true, true, true, false];
const oldSelects = [{
select: true,
name: "AA"
},
{
select: true,
name: "AA"
},
{
select: true,
name: "AA"
},
{
select: true,
name: "AA"
},
{
select: true,
name: "AA"
}
];
const newSelect = oldSelects.map((el, i) => ({
select: selects[i],
name: el.name
}));
console.log(newSelect);
Hey you can map the old array to a new one.
const selects = [false, true, true, true, false];
const oldSelects = [{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
];
const newSelect = oldSelects.map((object, index) => {
object['select'] = selects[index]
return object;
})
console.log(newSelect)
Using forEach
const selects = [false, true, true, true, false];
const oldSelects = [{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
];
const newSelects = []
oldSelects.forEach((selectItem, index) => newSelects.push({...selectItem, select: selects[index]}))
console.log(newSelects)
Using map
const selects = [false, true, true, true, false];
const oldSelects = [{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
{
select: true,
name: 'AA'
},
];
const newSelects = oldSelects.map((selectItem, index) => ({...selectItem, select: selects[index]}))
console.log(newSelects)

Parsing JSON responses and looking for specific variables

I need to parse through and look for a specific id. In the code below I need to be able to pull out the id number. It looks like this "itemIds":["918e337d-82ae-4e91-bdc3-16ad06572e21". I need to be able to pull the number "918e337d-82ae-4e91-bdc3-16ad06572e21". I have been having trouble understanding this concept. If you could send how or the actual code to do it . That would be very much appreciated.
{"dbSessionTokenMap":{"CXO_PC_ST":"e5b96399-fefc-4d9d-93ba-2aa1059008ce|{\"mtoken\":\"301:12#90271897#2=60818072#7=100439087\"}"},"id":"e5b96399-fefc-4d9d-93ba-2aa1059008ce","checkoutFlowType":"Guest","cartId":"ffd6cb2f-efc2-47b2-96d9-52d2cfb3d69b","items":[{"id":"918e337d-82ae-4e91-bdc3-16ad06572e21","offerId":"864A02B3BF7442A4802E6DF7BA2EDA28","productId":"1ZPTYHZN85S6","productName":"Pokemon Assorted Lot of 50 Single Cards [Any Series]","itemId":127446742,"sellerId":"A577588AB81D43AE9E7F468183B3568A","thumbnailUrl":"https://i5.walmartimages.com/asr/aa6ed747-9cd0-44dc-b927-44bc2b7e1ca7_1.62c435484d4015af1c325e9cdeeb3662.jpeg?odnHeight=100&odnWidth=100&odnBg=FFFFFF","legacySellerId":3340,"productClassType":"REGULAR","quantity":1,"unitPrice":8.61,"type":"REGULAR","price":8.61,"unitOfMeasure":"EA","hasCarePlan":false,"brand":"Pok?mon","discount":{},"rhPath":"20000:25000:25003:25114:25333","isWarrantyEligible":false,"category":"0:4171:3318550:617941:8920388","primaryCategory":"Home Page/Toys/Shop Toys by Age/Toys for Kids 5 to 7 Years/Toys for Kids 5 to 7 Years","isCarePlan":false,"isEgiftCard":false,"isAssociateDiscountEligible":false,"isShippingPassEligible":false,"isTwoDayShippingEligible":false,"classId":"5","maxQuantityPerOrder":100,"isSubstitutable":false,"isInstaWatch":false,"isAlcoholic":false,"isSnapEligible":false,"isAgeRestricted":false,"isSubstitutionsAllowed":false,"fulfillmentSelection":{"fulfillmentOption":"S2H","shipMethod":"STANDARD","availableQuantity":172},"servicePlanType":"NONE","errors":[],"wfsEnabled":false,"isAlcohol":false}],"shipping":{"postalCode":"82001","city":"CHEYENNE","state":"WY"},"promotions":[{"promotionId":"1c2cbad1-205e-425f-9297-8629d68e97f6","okToPayAwards":[{"applyTo":"CART_FULFILLMENT_PRICE","actionType":"AWARD","name":"DS_Donors_Choose_Teachers_Card","awardType":"OK_TO_PAY","description":"DonorsChoose Card","applicableTo":{"ITEM_TAX":true,"SHIP_PRICE":true,"SHIP_TAX":true,"FEE":true,"ITEM_PRICE":true},"asset":{"image":"https://i5.walmartimages.com/dfw/63fd9f59-e0cf/455269aa-c4e8-46a5-8d76-5d4b458e1269/v1/Select_gift_card.png","imageAlt":""},"awardEligibleItemIds":[],"awardEligibleTotalsByItemId":{}}],"dsEligibleItemIds":[],"dsEligibleTotals":{}}],"summary":{"subTotal":8.61,"shippingIsEstimate":false,"taxIsEstimate":true,"grandTotal":8.61,"quantityTotal":1,"amountOwed":8.61,"merchandisingFeesTotal":0,"shippingCosts":[{"label":"Top Cut Central shipping","type":"marketplace_shipping","cost":0.0}],"shippingTotal":0.0,"hasSurcharge":false,"preTaxTotal":8.61,"addOnServicesTotal":0,"itemsSubTotal":8.61},"pickupPeople":[],"email":"","buyer":{"customerAccountId":"9afb345e-74b8-4afb-93d0-4bf52697e18f","isGuestSignupRequired":false,"isGuest":true,"isAssociate":false,"applyAssociateDiscount":false},"allowedPaymentTypes":[{"type":"CREDITCARD","cvvRequired":true},{"type":"PAYPAL","cvvRequired":false},{"type":"GIFTCARD","cvvRequired":false},{"type":"VISA_CHECKOUT","cvvRequired":false},{"type":"MASTERPASS","cvvRequired":false},{"type":"CHASEPAY","cvvRequired":false},{"type":"AMEX_CHECKOUT","cvvRequired":false}],"registries":[],"payments":[],"cardsToDisable":[],"allowedPaymentPreferences":[],"isRCFEligible":false,"isMarketPlaceItemsExist":true,"version":"v3","shippingCategory":{"shippingGroups":[{"itemIds":["918e337d-82ae-4e91-bdc3-16ad06572e21"],"seller":"Top Cut Central","defaultSelection":true,"fulfillmentOption":"S2H","shippingGroupOptions":[{"method":"EXPEDITED","methodDisplay":"Expedited","selected":false,"charge":8.99,"deliveryDate":1606766400000,"availableDate":1606766400000,"fulfillmentOption":"S2H","onlineStoreId":0,"isThresholdShipMethod":false},{"method":"STANDARD","methodDisplay":"Standard","selected":true,"charge":0.0,"deliveryDate":1606939200000,"availableDate":1606939200000,"fulfillmentOption":"S2H","onlineStoreId":0,"isThresholdShipMethod":false}],"isEdelivery":false,"hasWFSItem":false,"itemSellerGroups":[]}]},"entityErrors":[],"oneDaySelected":false,"paymentWithBagFee":false,"giftDetails":{"giftOrder":false,"hasGiftEligibleItem":false,"xoGiftingOptIn":false},"canApplyDetails":[],"dbName":"e5b96399-fefc-4d9d-93ba-2aa1059008ce|C","jwt":"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI1MjdmZTRjYi0wZjI5LTRjZWYtOWRiOS00Yzc1YWQ5MTMwNTQiLCJpYXQiOjE2MDYwOTY0NjMsImlzcyI6IjU3YjM0ZTNhZGE1MjkzMGEwYzBjYTFjOSIsIk9yZ1VuaXRJZCI6IjU2ZWJiMTJkZGE1MjkzMWRhOGZlMDc5YSIsIlJlZmVyZW5jZUlkIjoiZTViOTYzOTktZmVmYy00ZDlkLTkzYmEtMmFhMTA1OTAwOGNlIn0.-ta5UQLkJtXNR5yP2dOhDiDMF9dPpbfktAJu7z22kNM"}
Edit Below! Edit Below! Edit Below!
For future visitors -
I like to use split to find what I specifically need. For example for this problem I had above. I would just use
let myId = string.split(`"itemIds":["`)[1].split('"')[0]
This should work well and I use this method all the time. If you have any better methods feel free to reply or leave an answer. You can also use JSON.parse(your data) and look for your specific variable that way. This article should also help you understand how to use it. https://www.tutorialrepublic.com/javascript-tutorial/javascript-json-parsing.php
First you need to determine which prop will you get the value of? And then try this, in this case I will get "itemIds" so my findProp function will take 2 parameters:
const myObj = {
dbSessionTokenMap: {
CXO_PC_ST:
'e5b96399-fefc-4d9d-93ba-2aa1059008ce|{"mtoken":"301:12#90271897#2=60818072#7=100439087"}',
},
id: "e5b96399-fefc-4d9d-93ba-2aa1059008ce",
checkoutFlowType: "Guest",
cartId: "ffd6cb2f-efc2-47b2-96d9-52d2cfb3d69b",
items: [
{
id: "918e337d-82ae-4e91-bdc3-16ad06572e21",
offerId: "864A02B3BF7442A4802E6DF7BA2EDA28",
productId: "1ZPTYHZN85S6",
productName: "Pokemon Assorted Lot of 50 Single Cards [Any Series]",
itemId: 127446742,
sellerId: "A577588AB81D43AE9E7F468183B3568A",
thumbnailUrl:
"https://i5.walmartimages.com/asr/aa6ed747-9cd0-44dc-b927-44bc2b7e1ca7_1.62c435484d4015af1c325e9cdeeb3662.jpeg?odnHeight=100&odnWidth=100&odnBg=FFFFFF",
legacySellerId: 3340,
productClassType: "REGULAR",
quantity: 1,
unitPrice: 8.61,
type: "REGULAR",
price: 8.61,
unitOfMeasure: "EA",
hasCarePlan: false,
brand: "Pok?mon",
discount: {},
rhPath: "20000:25000:25003:25114:25333",
isWarrantyEligible: false,
category: "0:4171:3318550:617941:8920388",
primaryCategory:
"Home Page/Toys/Shop Toys by Age/Toys for Kids 5 to 7 Years/Toys for Kids 5 to 7 Years",
isCarePlan: false,
isEgiftCard: false,
isAssociateDiscountEligible: false,
isShippingPassEligible: false,
isTwoDayShippingEligible: false,
classId: "5",
maxQuantityPerOrder: 100,
isSubstitutable: false,
isInstaWatch: false,
isAlcoholic: false,
isSnapEligible: false,
isAgeRestricted: false,
isSubstitutionsAllowed: false,
fulfillmentSelection: {
fulfillmentOption: "S2H",
shipMethod: "STANDARD",
availableQuantity: 172,
},
servicePlanType: "NONE",
errors: [],
wfsEnabled: false,
isAlcohol: false,
},
],
shipping: { postalCode: "82001", city: "CHEYENNE", state: "WY" },
promotions: [
{
promotionId: "1c2cbad1-205e-425f-9297-8629d68e97f6",
okToPayAwards: [
{
applyTo: "CART_FULFILLMENT_PRICE",
actionType: "AWARD",
name: "DS_Donors_Choose_Teachers_Card",
awardType: "OK_TO_PAY",
description: "DonorsChoose Card",
applicableTo: {
ITEM_TAX: true,
SHIP_PRICE: true,
SHIP_TAX: true,
FEE: true,
ITEM_PRICE: true,
},
asset: {
image:
"https://i5.walmartimages.com/dfw/63fd9f59-e0cf/455269aa-c4e8-46a5-8d76-5d4b458e1269/v1/Select_gift_card.png",
imageAlt: "",
},
awardEligibleItemIds: [],
awardEligibleTotalsByItemId: {},
},
],
dsEligibleItemIds: [],
dsEligibleTotals: {},
},
],
summary: {
subTotal: 8.61,
shippingIsEstimate: false,
taxIsEstimate: true,
grandTotal: 8.61,
quantityTotal: 1,
amountOwed: 8.61,
merchandisingFeesTotal: 0,
shippingCosts: [
{
label: "Top Cut Central shipping",
type: "marketplace_shipping",
cost: 0.0,
},
],
shippingTotal: 0.0,
hasSurcharge: false,
preTaxTotal: 8.61,
addOnServicesTotal: 0,
itemsSubTotal: 8.61,
},
pickupPeople: [],
email: "",
buyer: {
customerAccountId: "9afb345e-74b8-4afb-93d0-4bf52697e18f",
isGuestSignupRequired: false,
isGuest: true,
isAssociate: false,
applyAssociateDiscount: false,
},
allowedPaymentTypes: [
{ type: "CREDITCARD", cvvRequired: true },
{ type: "PAYPAL", cvvRequired: false },
{ type: "GIFTCARD", cvvRequired: false },
{ type: "VISA_CHECKOUT", cvvRequired: false },
{ type: "MASTERPASS", cvvRequired: false },
{ type: "CHASEPAY", cvvRequired: false },
{ type: "AMEX_CHECKOUT", cvvRequired: false },
],
registries: [],
payments: [],
cardsToDisable: [],
allowedPaymentPreferences: [],
isRCFEligible: false,
isMarketPlaceItemsExist: true,
version: "v3",
shippingCategory: {
shippingGroups: [
{
itemIds: ["918e337d-82ae-4e91-bdc3-16ad06572e21"],
seller: "Top Cut Central",
defaultSelection: true,
fulfillmentOption: "S2H",
shippingGroupOptions: [
{
method: "EXPEDITED",
methodDisplay: "Expedited",
selected: false,
charge: 8.99,
deliveryDate: 1606766400000,
availableDate: 1606766400000,
fulfillmentOption: "S2H",
onlineStoreId: 0,
isThresholdShipMethod: false,
},
{
method: "STANDARD",
methodDisplay: "Standard",
selected: true,
charge: 0.0,
deliveryDate: 1606939200000,
availableDate: 1606939200000,
fulfillmentOption: "S2H",
onlineStoreId: 0,
isThresholdShipMethod: false,
},
],
isEdelivery: false,
hasWFSItem: false,
itemSellerGroups: [],
},
],
},
entityErrors: [],
oneDaySelected: false,
paymentWithBagFee: false,
giftDetails: {
giftOrder: false,
hasGiftEligibleItem: false,
xoGiftingOptIn: false,
},
canApplyDetails: [],
dbName: "e5b96399-fefc-4d9d-93ba-2aa1059008ce|C",
jwt:
"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI1MjdmZTRjYi0wZjI5LTRjZWYtOWRiOS00Yzc1YWQ5MTMwNTQiLCJpYXQiOjE2MDYwOTY0NjMsImlzcyI6IjU3YjM0ZTNhZGE1MjkzMGEwYzBjYTFjOSIsIk9yZ1VuaXRJZCI6IjU2ZWJiMTJkZGE1MjkzMWRhOGZlMDc5YSIsIlJlZmVyZW5jZUlkIjoiZTViOTYzOTktZmVmYy00ZDlkLTkzYmEtMmFhMTA1OTAwOGNlIn0.-ta5UQLkJtXNR5yP2dOhDiDMF9dPpbfktAJu7z22kNM",
};
const findProp = (obj, prop, out) => {
let i,
proto = Object.prototype,
ts = proto.toString,
hasOwn = proto.hasOwnProperty.bind(obj);
if ("[object Array]" !== ts.call(out)) {
out = [];
}
for (i in obj) {
if (hasOwn(i)) {
if (i === prop) {
out.push(obj[i]);
} else if (
"[object Array]" === ts.call(obj[i]) ||
"[object Object]" === ts.call(obj[i])
) {
findProp(obj[i], prop, out);
}
}
}
return out;
};
console.log(findProp(myObj, "itemIds"));

How to iterate a nested object using map function?

I had used for loop to iterate nested objects, I am trying to replace forEach with the map function, without success. Can anyone help me with this?
schema.js
const products_schema = {
product_name: {
auto: false,
type: "string",
min: 5,
max: 10,
special_characters: ['_', ' '],
numbers: true,
alphabet: true,
required: true,
correct: ""
},
product_image: {
auto: false,
type: "array:string",
min: 0,
max: 50,
required: true
}
}
const specification_schema = {
brand: {
auto: false,
type: "string",
min: 10,
max: 50,
special_characters: ['_', ' '],
numbers: true,
alphabet: true,
required: true
}
}
let schema = {
products_schema:products_schema,
specification_schema:specification_schema
}
for(var key in schema)
{
var value = schema[key]
Object.keys(value).forEach(key => console.log(value[key].type));
}
"Expected output:"
string
array:string
string
use Object.values then use map to return only type property.
const products_schema = {
product_name: {
auto: false,
type: "string",
min: 5,
max: 10,
special_characters: ['_', ' '],
numbers: true,
alphabet: true,
required: true,
correct: ""
},
product_image: {
auto: false,
type: "array:string",
min: 0,
max: 50,
required: true
}
}
const specification_schema = {
brand: {
auto: false,
type: "string",
min: 10,
max: 50,
special_characters: ['_', ' '],
numbers: true,
alphabet: true,
required: true
}
}
let schema = {
products_schema:products_schema,
specification_schema:specification_schema
}
const mergedObjects = {...products_schema, ...specification_schema};
const output = Object.values(mergedObjects).map(({type}) => type);
console.log(output);
You could use nested Object.values():
const products_schema={product_name:{auto:false,type:"string",min:5,max:10,special_characters:['_',' '],numbers:true,alphabet:true,required:true,correct:""},product_image:{auto:false,type:"array:string",min:0,max:50,required:true}},
specification_schema={brand:{auto:false,type:"string",min:10,max:50,special_characters:['_',' '],numbers:true,alphabet:true,required:true}},
schema={ products_schema, specification_schema }
Object.values(schema).forEach(o => {
Object.values(o).forEach(a => console.log(a.type))
})
If you want to get an array of nested type you could use flatMap
const products_schema={product_name:{auto:false,type:"string",min:5,max:10,special_characters:['_',' '],numbers:true,alphabet:true,required:true,correct:""},product_image:{auto:false,type:"array:string",min:0,max:50,required:true}},
specification_schema={brand:{auto:false,type:"string",min:10,max:50,special_characters:['_',' '],numbers:true,alphabet:true,required:true}},
schema={ products_schema, specification_schema }
const types = Object.values(schema).flatMap(o =>
Object.values(o).map(a => a.type)
)
console.log(types)
If flatMap is not supported, you could simply use the first snippet and push to an array instead of logging it to the console.
const output = [];
Object.values(schema).forEach(o =>
Object.values(o).forEach(a => output.push(a.type))
)

Edit the next jqgrid row on hitting enter key

I have a jqgrid in which I use inline edit. My requirement is that, on hitting enter key I should be able to save the current row, and the next row should be editable with the cursor present in any of the columns of that row.
I have tried using aftersavefunc, but I couldn't make it work. Also, using afterSavecell doesn't work in this case as more than one cell needs to be edited. I just need a solution wherein I can call the editrow method after saverow has been completed on the Click of enter button.
$(function () {
oldInfoDialog = $.jgrid.info_dialog;
$.extend($.jgrid.inlineEdit, { keys: true });
// tried to override the default aftersavefunc but didn't work.
$.extend($.jgrid.defaults, {
ajaxRowOptions: {
aftersavefunc: function (rowid, response, options) {
debugger;
var increment = 1;
var lastRowInd = jQuery("#grid").jqGrid("getGridParam", "reccount")
var iRow = $('#' + rowid)[0].rowIndex;
if (iRow + increment == 0 || iRow + increment == lastRowInd + 1) {// we could re-edit current cell or wrap
return;
}
else
var testid1 = iRow + increment
var testid = jQuery('#grid tr:eq(' + testid1 + ')').attr('id');
jQuery('#grid').editRow(testid, true);
}
}
});
// use custom alert for data validations
$.extend($.jgrid, {
info_dialog: function (caption, content, c_b, modalopt) {
if (useCustomDialog) {
// display custom dialog
useCustomDialog = false;
//var message_box = content.split(":");
alert(content.split(":")[1]);
} else {
return oldInfoDialog.apply(this, arguments);
}
}
});
$("#grid").jqGrid({
url: "/TodoList/GetList",
datatype: 'json',
mtype: 'Get',
colNames: ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
colModel: [
{ key: false, hidden: true, name: 'A', index: 'A', editable: true, frozen: true },
{ key: false, hidden: true, name: 'B', index: 'B', editable: true },
{ key: true, hidden: true, name: 'C', index: 'C', editable: true },
{
key: false, hidden: false, name: 'D', index: 'D', editable: true
},
{
key: false, hidden: false, name: 'E', index: 'E', editable: true,
editrules: {
custom: true,
custom_func: function (val) {
useCustomDialog = false;
debugger;
// var val1 = val.value;
var message = "";
var num = new Number(val);
var selRowId = $("#grid").jqGrid("getGridParam", "selrow");
var pattern = /^(0|[1-9][0-9]{0,2}(?:([0-9]{3})*|[0-9]*))(\.[0-9]{1,2}){0,1}$/;
if (!pattern.test(num)) {
message = ":Please enter a positive number in valid format with upto 2 decimal places and without commas.";
useCustomDialog = true
isError = true;
return [false, message];
}
else {
return [true];
}
}
},
editoptions: {
dataInit: function (element) {
useCustomDialog = false;
$(element).focusout(function () {
var val1 = element.value;
var num = new Number(val1);
var selRowId = $("#grid").jqGrid("getGridParam", "selrow");
})
}
}
},
{
key: false, hidden: false, name: 'F', index: 'F', editable: true, editoptions: {
dataInit: function (element) {
$(element).attr("readonly", "readonly");
}
}
}
, {
key: false, hidden: false, name: 'G', index: 'G', editable: true,
editoptions: {
dataInit: function (element) {
$(element).attr("readonly", "readonly");
}
}
}
],
onSelectRow: function (id) {
if (id && id !== lastsel2) {
if (useCustomDialog === false) {
jQuery('#grid').saveRow(lastsel2);
jQuery('#grid').editRow(id, true);
lastsel2 = id;
}
}
},
editurl: "/TodoList/Save",
caption: "Input Types",
pager: jQuery('#pagersub'),
height: '100%',
viewrecords: true,
caption: 'Data Entry',
emptyrecords: 'No records to display',
jsonReader: {
root: "rows",
page: 1,
total: "total",
records: 2,
repeatitems: false,
Id: "0"
},
autowidth: true,
multiselect: false
})
});

Find object in collection with fuzzy matching

I have a collection that looks something like this:
const collection = [
{
name: 'THIS_ITEM',
conditions: {
oneCondition: false,
anotherCondition: false,
yourCondition: false,
myCondition: false
}
}, {
name: 'THAT_ITEM',
conditions: {
oneCondition: false,
anotherCondition: false,
yourCondition: true,
myCondition: false
}
}, {
name: 'THOSE_ITEMS',
conditions: {
oneCondition: true,
anotherCondition: false,
yourCondition: null,
myCondition: false
}
}
];
… and later an object that looks like this:
const condition = {
oneCondition: true,
anotherCondition: false,
yourCondition: true,
myCondition: false
};
I’m trying to match the condition object against the nested conditions objects in collection to find the one that matches so I can retrieve the name property from the matching entry.
The thing that’s throwing me for a loop is the fact that the conditions properties can have “fuzzy” values. By that I mean that if any properties in the source collection are set to true or false they MUST match the values in condition exactly. But if the property in the source collection has a value of null it can match either true or false.
Example:
These would match:
const condition = {
oneCondition: true,
anotherCondition: false,
yourCondition: true,
myCondition: false
};
const collection = [
…
}, {
name: 'THOSE_ITEMS',
conditions: {
oneCondition: true,
anotherCondition: false,
yourCondition: null,
myCondition: false
}
}
];
These would not:
const condition = {
oneCondition: true,
anotherCondition: false,
yourCondition: true,
myCondition: false
};
const collection = [
…
}, {
name: 'THAT_ITEM',
conditions: {
oneCondition: false,
anotherCondition: false,
yourCondition: true,
myCondition: false
}
}, {
…
];
Any suggestions? I’m using Lodash but can’t seem to imagine any solution without an overly-verbose and nested concoction.
You could use Array#filter with Array#every for the conditions and test against null value as wildcard.
var collection = [{ name: 'THIS_ITEM', conditions: { oneCondition: false, anotherCondition: false, yourCondition: false, myCondition: false } }, { name: 'THAT_ITEM', conditions: { oneCondition: false, anotherCondition: false, yourCondition: true, myCondition: false } }, { name: 'THOSE_ITEMS', conditions: { oneCondition: true, anotherCondition: false, yourCondition: null, myCondition: false } }],
condition = { oneCondition: true, anotherCondition: false, yourCondition: true, myCondition: false },
result = collection.filter(o =>
Object.keys(condition).every(k =>
o.conditions[k] === null || o.conditions[k] === condition[k]
)
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use lodash#filter with lodash#isMatch and lodash#omitBy to match the condition against a collection object's condition that doesn't contain any null values.
const result = _.filter(collection, v =>
_.isMatch(condition, _.omitBy(v.conditions, _.isNull))
);
const collection = [
{
name: 'THIS_ITEM',
conditions: {
oneCondition: false,
anotherCondition: false,
yourCondition: false,
myCondition: false
}
}, {
name: 'THAT_ITEM',
conditions: {
oneCondition: false,
anotherCondition: false,
yourCondition: true,
myCondition: false
}
}, {
name: 'THOSE_ITEMS',
conditions: {
oneCondition: true,
anotherCondition: false,
yourCondition: null,
myCondition: false
}
}
];
const condition = {
oneCondition: true,
anotherCondition: false,
yourCondition: true,
myCondition: false
};
const result = _.filter(collection, v =>
_.isMatch(condition, _.omitBy(v.conditions, _.isNull))
);
console.log(result);
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
You can filter the collecting using lodash's _.isMatchWith():
const condition = {"oneCondition":true,"anotherCondition":false,"yourCondition":true,"myCondition":false};
const collection = [{"name":"1","conditions":{"oneCondition":true,"anotherCondition":false,"yourCondition":true,"myCondition":false}},{"name":"2","conditions":{"oneCondition":true,"anotherCondition":false,"yourCondition":false,"myCondition":false}},{"name":"3","conditions":{"oneCondition":true,"anotherCondition":false,"yourCondition":null,"myCondition":false}}];
const result = collection.filter(({ conditions }) =>
_.isMatchWith(condition, conditions, (objValue, othValue) =>
objValue === null || othValue === null || objValue === othValue) // if at least one of the values is null or they are equal
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
You can use a combination of lodash
.filter(), .every() and .isEqual() methods to loop over the collection and filter only items which have the same conditions as your object:
_.filter(collection, function(c) {
return _.every(_.keys(condition), function(currentKey) {
return c.conditions[currentKey] === null ||
_.isEqual(c.conditions[currentKey], condition[currentKey]);
});
});
Demo:
const collection = [{
name: 'THIS_ITEM',
conditions: {
oneCondition: false,
anotherCondition: false,
yourCondition: false,
myCondition: false
}
}, {
name: 'THAT_ITEM',
conditions: {
oneCondition: false,
anotherCondition: false,
yourCondition: true,
myCondition: false
}
}, {
name: 'THOSE_ITEMS',
conditions: {
oneCondition: true,
anotherCondition: false,
yourCondition: null,
myCondition: false
}
}];
const condition = {
oneCondition: true,
anotherCondition: false,
yourCondition: true,
myCondition: false
};
var result = _.filter(collection, function(c) {
return _.every(_.keys(condition), function(currentKey) {
return c.conditions[currentKey] === null ||
_.isEqual(c.conditions[currentKey], condition[currentKey]);
});
});
console.log(result);
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
<script src="http://underscorejs.org/underscore-min.js"></script>

Categories

Resources