Actions, resources, and condition keys for AWS Directory Service
AWS Directory Service (service prefix:
ds
) provides the following service-specific resources, actions, and condition context keys for use in IAM permission policies.
References:
-
Learn how to configure this service .
-
View a list of the API operations available for this service .
-
Learn how to secure this service and its resources by using IAM permission policies.
Topics
Actions defined by AWS Directory Service
You can specify the following actions in the
Action
element of an IAM policy statement. Use policies to grant permissions to perform an operation in AWS. When you use an action in a policy, you usually allow or deny access to the API operation or CLI command with the same name. However, in some cases, a single action controls access to more than one operation. Alternatively, some operations require several different actions.
The
Resource types
column of the Actions table indicates whether each action supports resource-level permissions. If there is no value for this column, you must specify all resources ("*") to which the policy applies in the
Resource
element of your policy statement. If the column includes a resource type, then you can specify an ARN of that type in a statement with that action. If the action has one or more required resources, the caller must have permission to use the action with those resources. Required resources are indicated in the table with an asterisk (*). If you limit resource access with the
Resource
element in an IAM policy, you must include an ARN or pattern for each required resource type. Some actions support multiple resource types. If the resource type is optional (not indicated as required), then you can choose to use one of the optional resource types.
The
Condition keys
column of the Actions table includes keys that you can specify in a policy statement's
Condition
element. For more information on the condition keys that are associated with resources for the service, see the
Condition keys
column of the Resource types table.
For details about the columns in the following table, see Actions table .
| Actions | Description | Access level | Resource types (*required) | Condition keys | Dependent actions |
|---|---|---|---|---|---|
| AcceptSharedDirectory | Grants permission to accept a directory sharing request that was sent from the directory owner account | Write | |||
| AddIpRoutes | Grants permission to add a CIDR address block to correctly route traffic to and from your Microsoft AD on Amazon Web Services | Write |
ec2:AuthorizeSecurityGroupEgress ec2:AuthorizeSecurityGroupIngress ec2:DescribeSecurityGroups |
||
| AddRegion | Grants permission to add two domain controllers in the specified Region for the specified directory | Write |
ec2:AuthorizeSecurityGroupEgress ec2:AuthorizeSecurityGroupIngress ec2:CreateNetworkInterface ec2:CreateSecurityGroup ec2:CreateTags ec2:DescribeNetworkInterfaces ec2:DescribeSubnets ec2:DescribeVpcs |
||
| AddTagsToResource | Grants permission to add or overwrite one or more tags for the specified Amazon Directory Services directory | Tagging |
ec2:CreateTags |
||
| AuthorizeApplication [permission only] | Grants permission to authorize an application for your AWS Directory | Write | |||
| CancelSchemaExtension | Grants permission to cancel an in-progress schema extension to a Microsoft AD directory | Write | |||
| CheckAlias [permission only] | Grants permission to verify that the alias is available for use | Read | |||
| ConnectDirectory | Grants permission to create an AD Connector to connect to an on-premises directory | Write |
ec2:AuthorizeSecurityGroupEgress ec2:AuthorizeSecurityGroupIngress ec2:CreateNetworkInterface ec2:CreateSecurityGroup ec2:CreateTags ec2:DescribeNetworkInterfaces ec2:DescribeSubnets ec2:DescribeVpcs |
||
| CreateAlias | Grants permission to create an alias for a directory and assigns the alias to the directory | Write | |||
| CreateComputer | Grants permission to create a computer account in the specified directory, and joins the computer to the directory | Write | |||
| CreateConditionalForwarder | Grants permission to create a conditional forwarder associated with your AWS directory | Write | |||
| CreateDirectory | Grants permission to create a Simple AD directory | Write |
ec2:AuthorizeSecurityGroupEgress ec2:AuthorizeSecurityGroupIngress ec2:CreateNetworkInterface ec2:CreateSecurityGroup ec2:CreateTags ec2:DescribeNetworkInterfaces ec2:DescribeSubnets ec2:DescribeVpcs |
||
| CreateIdentityPoolDirectory [permission only] | Grants permission to create an IdentityPool Directory in the AWS cloud | Write | |||
| CreateLogSubscription | Grants permission to create a subscription to forward real time Directory Service domain controller security logs to the specified CloudWatch log group in your AWS account | Write | |||
| CreateMicrosoftAD | Grants permission to create a Microsoft AD in the AWS cloud | Write |
ec2:AuthorizeSecurityGroupEgress ec2:AuthorizeSecurityGroupIngress ec2:CreateNetworkInterface ec2:CreateSecurityGroup ec2:CreateTags ec2:DescribeNetworkInterfaces ec2:DescribeSubnets ec2:DescribeVpcs |
||
| CreateSnapshot | Grants permission to create a snapshot of a Simple AD or Microsoft AD directory in the AWS cloud | Write | |||
| CreateTrust | Grants permission to initiate the creation of the AWS side of a trust relationship between a Microsoft AD in the AWS cloud and an external domain | Write | |||
| DeleteConditionalForwarder | Grants permission to delete a conditional forwarder that has been set up for your AWS directory | Write | |||
| DeleteDirectory | Grants permission to delete an AWS Directory Service directory | Write |
ec2:DeleteNetworkInterface ec2:DeleteSecurityGroup ec2:DescribeNetworkInterfaces ec2:RevokeSecurityGroupEgress ec2:RevokeSecurityGroupIngress |
||
| DeleteLogSubscription | Grants permission to delete the specified log subscription | Write | |||
| DeleteSnapshot | Grants permission to delete a directory snapshot | Write | |||
| DeleteTrust | Grants permission to delete an existing trust relationship between your Microsoft AD in the AWS cloud and an external domain | Write | |||
| DeregisterCertificate | Grants permission to delete from the system the certificate that was registered for a secured LDAP connection | Write | |||
| DeregisterEventTopic | Grants permission to remove the specified directory as a publisher to the specified SNS topic | Write | |||
| DescribeCertificate | Grants permission to display information about the certificate registered for a secured LDAP connection | Read | |||
| DescribeClientAuthenticationSettings | Grants permission to retrieve information about the type of client authentication for the specified directory, if the type is specified. If no type is specified, information about all client authentication types that are supported for the specified directory is retrieved. Currently, only SmartCard is supported | Read | |||
| DescribeConditionalForwarders | Grants permission to obtain information about the conditional forwarders for this account | Read | |||
| DescribeDirectories | Grants permission to obtain information about the directories that belong to this account | List | |||
| DescribeDomainControllers | Grants permission to provide information about any domain controllers in your directory | Read | |||
| DescribeEventTopics | Grants permission to obtain information about which SNS topics receive status messages from the specified directory | Read | |||
| DescribeLDAPSSettings | Grants permission to describe the status of LDAP security for the specified directory | Read | |||
| DescribeRegions | Grants permission to provide information about the Regions that are configured for multi-Region replication | Read | |||
| DescribeSettings | Grants permission to retrieve information about the configurable settings for the specified directory | Read | |||
| DescribeSharedDirectories | Grants permission to return the shared directories in your account | Read | |||
| DescribeSnapshots | Grants permission to obtain information about the directory snapshots that belong to this account | Read | |||
| DescribeTrusts | Grants permission to obtain information about the trust relationships for this account | Read | |||
| DescribeUpdateDirectory | Grants permission to describe the updates of a directory for a particular update type | Read | |||
| DisableClientAuthentication | Grants permission to disable alternative client authentication methods for the specified directory | Write | |||
| DisableLDAPS | Grants permission to deactivate LDAP secure calls for the specified directory | Write | |||
| DisableRadius | Grants permission to disable multi-factor authentication (MFA) with the Remote Authentication Dial In User Service (RADIUS) server for an AD Connector directory | Write | |||
| DisableSso | Grants permission to disable single-sign on for a directory | Write | |||
| EnableClientAuthentication | Grants permission to enable alternative client authentication methods for the specified directory | Write | |||
| EnableLDAPS | Grants permission to activate the switch for the specific directory to always use LDAP secure calls | Write | |||
| EnableRadius | Grants permission to enable multi-factor authentication (MFA) with the Remote Authentication Dial In User Service (RADIUS) server for an AD Connector directory | Write | |||
| EnableSso | Grants permission to enable single-sign on for a directory | Write | |||
| GetAuthorizedApplicationDetails [permission only] | Grants permission to retrieve the details of the authorized applications on a directory | Read | |||
| GetDirectoryLimits | Grants permission to obtain directory limit information for the current region | Read | |||
| GetSnapshotLimits | Grants permission to obtain the manual snapshot limits for a directory | Read | |||
| ListAuthorizedApplications [permission only] | Grants permission to obtain the AWS applications authorized for a directory | Read | |||
| ListCertificates | Grants permission to list all the certificates registered for a secured LDAP connection, for the specified directory | List | |||
| ListIpRoutes | Grants permission to list the address blocks that you have added to a directory | Read | |||
| ListLogSubscriptions | Grants permission to list the active log subscriptions for the AWS account | Read | |||
| ListSchemaExtensions | Grants permission to list all schema extensions applied to a Microsoft AD Directory | List | |||
| ListTagsForResource | Grants permission to list all tags on an Amazon Directory Services directory | Read | |||
| RegisterCertificate | Grants permission to register a certificate for secured LDAP connection | Write | |||
| RegisterEventTopic | Grants permission to associate a directory with an SNS topic | Write |
sns:GetTopicAttributes |
||
| RejectSharedDirectory | Grants permission to reject a directory sharing request that was sent from the directory owner account | Write | |||
| RemoveIpRoutes | Grants permission to remove IP address blocks from a directory | Write | |||
| RemoveRegion | Grants permission to stop all replication and removes the domain controllers from the specified Region. You cannot remove the primary Region with this operation | Write | |||
| RemoveTagsFromResource | Grants permission to remove tags from an Amazon Directory Services directory | Tagging |
ec2:DeleteTags |
||
| ResetUserPassword | Grants permission to reset the password for any user in your AWS Managed Microsoft AD or Simple AD directory | Write | |||
| RestoreFromSnapshot | Grants permission to restore a directory using an existing directory snapshot | Write | |||
| ShareDirectory | Grants permission to share a specified directory in your AWS account (directory owner) with another AWS account (directory consumer). With this operation you can use your directory from any AWS account and from any Amazon VPC within an AWS Region | Write | |||
| StartSchemaExtension | Grants permission to apply a schema extension to a Microsoft AD directory | Write | |||
| UnauthorizeApplication [permission only] | Grants permission to unauthorize an application from your AWS Directory | Write | |||
| UnshareDirectory | Grants permission to stop the directory sharing between the directory owner and consumer accounts | Write | |||
| UpdateAuthorizedApplication [permission only] | Grants permission to update an authorized application for your AWS Directory | Write | |||
| UpdateConditionalForwarder | Grants permission to update a conditional forwarder that has been set up for your AWS directory | Write | |||
| UpdateDirectorySetup | Grants permission to update the directory for a particular update type | Write | |||
| UpdateNumberOfDomainControllers | Grants permission to add or remove domain controllers to or from the directory. Based on the difference between current value and new value (provided through this API call), domain controllers will be added or removed. It may take up to 45 minutes for any new domain controllers to become fully active once the requested number of domain controllers is updated. During this time, you cannot make another update request | Write | |||
| UpdateRadius | Grants permission to update the Remote Authentication Dial In User Service (RADIUS) server information for an AD Connector directory | Write | |||
| UpdateSettings | Grants permission to update the configurable settings for the specified directory | Write | |||
| UpdateTrust | Grants permission to update the trust that has been set up between your AWS Managed Microsoft AD directory and an on-premises Active Directory | Write | |||
| VerifyTrust | Grants permission to verify a trust relationship between your Microsoft AD in the AWS cloud and an external domain | Read |
Resource types defined by AWS Directory Service
The following resource types are defined by this service and can be used in the
Resource
element of IAM permission policy statements. Each action in the
Actions table
identifies the resource types that can be specified with that action. A resource type can also define which condition keys you can include in a policy. These keys are displayed in the last column of the Resource types table. For details about the columns in the following table, see
Resource types table
.
| Resource types | ARN | Condition keys |
|---|---|---|
| directory |
arn:$
{
Partition}:ds:$
{
Region}:$
{
Account}:directory/$
{
DirectoryId}
|
Condition keys for AWS Directory Service
AWS Directory Service defines the following condition keys that can be used in the
Condition
element of an IAM policy. You can use these keys to further refine the conditions under which the policy statement applies. For details about the columns in the following table, see
Condition keys table
.
To view the global condition keys that are available to all services, see Available global condition keys .
| Condition keys | Description | Type |
|---|---|---|
| aws:RequestTag/${TagKey} | Filters access by the value of the request to AWS DS | String |
| aws:ResourceTag/${TagKey} | Filters access by the AWS DS Resource being acted upon | String |
| aws:TagKeys | Filters access by the tag keys that are passed in the request | ArrayOfString |


Area of Triangle
Compute Area
Result :
Camel Case
Go
Camel Case :
Is it a Leap Year?
Check
Is it?

String Traverser
Go
Result:
Prime Numbers
Proceed
Result:


| | |
Methods defined here:
- __init__(self)
- This class is for the tile bag, it contains a list of letters. it had different functions to serve the
purpose of a tile bag: creating tiles, trading tiles, resetting the tile bag,
- create_letters(self)
- Create the right amount of tiles for each letter per the scrabble rulles.
for in range of .. extend a tuple of items into the tilebag list.
- get_amount_of_letters(self, amount)
- For each time amount is get a letter and append to list
:param amount: int value
:return: letter list
- get_tiles_left(self)
- :return: Return the amount of tiles left in the bag.
- reset_tile_bag(self)
- Reset the bag of tiles to begin position
- trade_leter(self, letter)
- Trade letter for another letter if the tile bag is not empty. extend the letter and return another letter
else return False
:param letter: string letter
:return: False or string letter
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|


--- title: nanmedian sidebar: function_reference_sidebar permalink: nanmedian.html folder: function_reference toc: false ---
FORMAT: Y = NANMEDIAN(X,DIM)
Median ignoring NaNs
This function enhances the functionality of NANMEDIAN as distributed in the MATLAB Statistics Toolbox and is meant as a replacement (hence the identical name).
NANMEDIAN(X,DIM) calculates the mean along any dimension of the N-D array X ignoring NaNs. If DIM is omitted NANMEDIAN averages along the first non-singleton dimension of X.
Similar replacements exist for NANMEAN, NANSTD, NANMIN, NANMAX, and NANSUM which are all part of the NaN-suite.


fgetcsv
(PHP 4, PHP 5, PHP 7)
fgetcsv — 从文件指针中读入一行并解析 CSV 字段
说明
array fgetcsv ( resource $handle [, int $length = 0 [, string $delimiter = ','
[, string $enclosure = '"' [, string $escape = '\\' ]]]] )
和 fgets() 类似，只除了 fgetcsv() 解析读入的行并找出 CSV 格式的字段然后返回一个
包含这些字段的数组。
参数
handle
一个由 fopen()、popen() 或 fsockopen() 产生的有效文件指针。
length
必须大于 CVS 文件内最长的一行。在 PHP 5 中该参数是可选的。如果忽略（在 PHP
5.0.4 以后的版本中设为 0）该参数的话，那么长度就没有限制，不过可能会影响执
行效率。
delimiter
设置字段分界符（只允许一个字符）。
enclosure
设置字段环绕符（只允许一个字符）。
escape
设置转义字符（只允许一个字符），默认是一个反斜杠。
返回值
返回包含读取字段的索引数组。
Note:
CSV 文件中的空行将被返回为一个包含有单个 null 字段的数组，不会被当成错误。
Note: 在读取在 Macintosh 电脑中或由其创建的文件时，如果 PHP 不能正确的识别
行结束符，启用运行时配置可选项 auto_detect_line_endings 也许可以解决此问题
。
如果提供了无效的文件指针，fgetcsv() 会返回 NULL。其他错误，包括碰到文件结束时返
回 FALSE，。
更新日志
版本 说明
5.3.0 增加了 escape 参数。
4.3.5 现在起 fgetcsv() 的操作是二进制安全的。
4.3.0 增加了 enclosure 参数。
范例
Example #1 读取并显示 CSV 文件的整个内容
$num fields in line $row:
\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "
\n";
}
}
fclose($handle);
}
?>
注释
Note:
该函数对区域设置是敏感的。比如说 LANG 设为 en_US.UTF-8 的话，单字节编码的文
件就会出现读取错误。
参见
• str_getcsv() - 解析 CSV 字符串为一个数组
• explode() - 使用一个字符串分割另一个字符串
• file() - 把整个文件读入一个数组中
• pack() - Pack data into binary string
• fputcsv() - 将行格式化为 CSV 并写入文件指针
User Contributed Notes 54 notes
===============================================================================
If you need to set auto_detect_line_endings to deal with Mac line endings, it
may seem obvious but remember it should be set before fopen, not after:
This will work:
This won't, you will still get concatenated fields at the new line position:
===============================================================================
Here is a OOP based importer similar to the one posted earlier. However, this
is slightly more flexible in that you can import huge files without running out
of memory, you just have to use a limit on the get() method
Sample usage for small files:-
-------------------------------------
get();
print_r($data);
?>
Sample usage for large files:-
-------------------------------------
get(2000))
{
print_r($data);
}
?>
And heres the class:-
-------------------------------------
fp = fopen($file_name, "r");
$this->parse_header = $parse_header;
$this->delimiter = $delimiter;
$this->length = $length;
$this->lines = $lines;
if ($this->parse_header)
{
$this->header = fgetcsv($this->fp, $this->length, $this->delimiter);
}
}
//--------------------------------------------------------------------
function __destruct()
{
if ($this->fp)
{
fclose($this->fp);
}
}
//--------------------------------------------------------------------
function get($max_lines=0)
{
//if $max_lines is set to 0, then get all the data
$data = array();
if ($max_lines > 0)
$line_count = 0;
else
$line_count = -1; // so loop limit is ignored
while ($line_count < $max_lines && ($row = fgetcsv($this->fp, $this->
length, $this->delimiter)) !== FALSE)
{
if ($this->parse_header)
{
foreach ($this->header as $i => $heading_i)
{
$row_new[$heading_i] = $row[$i];
}
$data[] = $row_new;
}
else
{
$data[] = $row;
}
if ($max_lines > 0)
$line_count++;
}
return $data;
}
//--------------------------------------------------------------------
}
?>
===============================================================================
beware of characters of binary value == 0, as they seem to make fgetcsv ignore
the remaining part of a line where they appear.
Maybe this is normal under some convention I don't know, but a file exported
from Excel had those as values for some cells *sometimes*, thus fgetcsv return
variable cell counts for different lines.
i'm using php 4.3
===============================================================================
A simple function to return 2 Dimensional array by parsing a CSV file.
===============================================================================
I needed a function to analyse a file for delimiters and line endings prior to
importing the file into MySQL using LOAD DATA LOCAL INFILE
I wrote this function to do the job, the results are (mostly) very accurate and
it works nicely with large files too.
',',
'semicolon' => ';',
'tab' => "\t",
'pipe' => '|',
'colon' => ':'
);
// specify allowed line endings
$line_endings = array(
'rn' => "\r\n",
'n' => "\n",
'r' => "\r",
'nr' => "\n\r"
);
// loop and count each line ending instance
foreach ($line_endings as $key => $value) {
$line_result[$key] = substr_count($contents, $value);
}
// sort by largest array value
asort($line_result);
// log to output array
$output['line_ending']['results'] = $line_result;
$output['line_ending']['count'] = end($line_result);
$output['line_ending']['key'] = key($line_result);
$output['line_ending']['value'] = $line_endings[$output['line_ending'][
'key']];
$lines = explode($output['line_ending']['value'], $contents);
// remove last line of array, as this maybe incomplete?
array_pop($lines);
// create a string from the legal lines
$complete_lines = implode(' ', $lines);
// log statistics to output array
$output['lines']['count'] = count($lines);
$output['lines']['length'] = strlen($complete_lines);
// loop and count each delimiter instance
foreach ($delimiters as $delimiter_key => $delimiter) {
$delimiter_result[$delimiter_key] = substr_count($complete_lines,
$delimiter);
}
// sort by largest array value
asort($delimiter_result);
// log statistics to output array with largest counts as the value
$output['delimiter']['results'] = $delimiter_result;
$output['delimiter']['count'] = end($delimiter_result);
$output['delimiter']['key'] = key($delimiter_result);
$output['delimiter']['value'] = $delimiters[$output['delimiter'][
'key']];
// capture ending memory usage
$output['peak_mem']['end'] = memory_get_peak_usage(true);
return $output;
}
?>
Example Usage:
,
// $Array['line_ending']['value'] => \r\n
?>
Full function output:
Array
(
[peak_mem] => Array
(
[start] => 786432
[end] => 786432
)
[line_ending] => Array
(
[results] => Array
(
[nr] => 0
[r] => 4
[n] => 4
[rn] => 4
)
[count] => 4
[key] => rn
[value] =>
)
[lines] => Array
(
[count] => 4
[length] => 94
)
[delimiter] => Array
(
[results] => Array
(
[colon] => 0
[semicolon] => 0
[pipe] => 0
[tab] => 1
[comma] => 17
)
[count] => 17
[key] => comma
[value] => ,
)
[read_kb] => 10
)
Enjoy!
Ashley
===============================================================================
Only problem with fgetcsv(), at least in PHP 4.x -- any stray slash in the data
that happens to come before a double-quote delimiter will break it -- ie, cause
the field delimiter to be escaped. I can't find a direct way to deal with it,
since fgetcsv() doesn't give you a chance to manipulate the line before it
reads it and parses it...I've had to change all occurrences of '\"' to '" in
the file first before feeding ot to fgetcsv(). Otherwise this is perfect for
that Microsoft-CSV formula, deals gracefully with all the issues.
===============================================================================
Note that fgetcsv, at least in PHP 5.3 or previous, will NOT work with UTF-16
encoded files. Your options are to convert the entire file to ISO-8859-1 (or
latin1), or convert line by line and convert each line into ISO-8859-1
encoding, then use str_getcsv (or compatible backwards-compatible
implementation). If you need to read non-latin alphabets, probably best to
convert to UTF-8.
See str_getcsv for a backwards-compatible version of it with PHP < 5.3, and see
utf8_decode for a function written by Rasmus Andersson which provides
utf16_decode. The modification I added was that the BOP appears at the top of
the file, then not on subsequent lines. So you need to store the endian-ness,
and then re-send it upon each subsequent line decoding. This modified version
returns the endianness, if it's not available:
Trying the "setlocale" trick did not work for me, e.g.
But that's perhaps because my platform didn't support it. However, fgetcsv only
supports single characters for the delimiter, etc. and complains if you pass in
a UTF-16 version of said character, so I gave up on that rather quickly.
Hope this is helpful to someone out there.
===============================================================================
Hier is an example for a CSV Iterator.
filePointer = fopen($file, 'r');
$this->delimiter = $delimiter;
}
catch (Exception $e) {
throw new Exception('The file "'.$file.'" cannot be read.');
}
}
/**
* This method resets the file pointer.
*
* @access public
*/
public function rewind() {
$this->rowCounter = 0;
rewind($this->filePointer);
}
/**
* This method returns the current csv row as a 2 dimensional array
*
* @access public
* @return array The current csv row as a 2 dimensional array
*/
public function current() {
$this->currentElement = fgetcsv($this->filePointer, self::ROW_SIZE,
$this->delimiter);
$this->rowCounter++;
return $this->currentElement;
}
/**
* This method returns the current row number.
*
* @access public
* @return int The current row number
*/
public function key() {
return $this->rowCounter;
}
/**
* This method checks if the end of file is reached.
*
* @access public
* @return boolean Returns true on EOF reached, false otherwise.
*/
public function next() {
return !feof($this->filePointer);
}
/**
* This method checks if the next row is a valid row.
*
* @access public
* @return boolean If the next row is a valid row.
*/
public function valid() {
if (!$this->next()) {
fclose($this->filePointer);
return false;
}
return true;
}
}
?>
Usage :
$data) {
// do somthing with $data
}
?>
===============================================================================
Parse from Microsoft Excel "Unicode Text (*.txt)" format:
$val ) {
$cols[$key] = trim( $cols[$key] );
$cols[$key] = iconv('UCS-2', 'UTF-8', $cols[$key]."\0") ;
$cols[$key] = str_replace('""', '"', $cols[$key]);
$cols[$key] = preg_replace("/^\"(.*)\"$/sim", "$1", $cols[$key]);
}
echo print_r($cols, 1);
}
}
?>
===============================================================================
NOTE: the 5th parameter was apparently not added until 5.3.0 yet the
documentation on this page fails to mention this.
===============================================================================
This is how to read a csv file into a multidimensional array.
===============================================================================
Newer PHP versions handle cvs files slightly different than older versions.
"Max Mustermann"|"Muster Road 34b"|"Berlin" |"Germany"
"Sophie Master" |"Riverstreet" |"Washington"|"USA"
The extra spaces behind a few fields in the example (which are useful, when you
manually manage a small csv database to align the columns) were ignored by
fgetcsv from PHP 4.3. With the new 4.4.1 release they get appended to the
string, so you end up with "Riverstreet " instead the expected
"Riverstreet".
Easy workaround is to just trim all fields after reading them in.
===============================================================================
The fgetcsv function seems to follow the MS excel conventions, which means:
- The quoting character is escaped by itself and not the back slash.
(i.e.Let's use the double quote (") as the quoting character:
Two double quotes "" will give a single " once parsed, if they are inside a
quoted field (otherwise neither of them will be removed).
\" will give \" whether it is in a quoted field or not (same for \\) , and
if a single double quote is inside a quoted field it will be removed. If it
is not inside a quoted field it will stay).
- leading and trailing spaces (\s or \t) are never removed, regardless of
whether they are in quoted fields or not.
- Line breaks within fields are dealt with correctly if they are in quoted
fields. (So previous comments stating the opposite are wrong, unless they are
using a different PHP version.... I am using 4.4.0.)
So fgetcsv if actually very complete and can deal with every possible
situation. (It does need help for macintosh line breaks though, as mentioned in
the help files.)
I wish I knew all this from the start. From my own benchmarks fgetcsv strikes a
very good compromise between memory consumption and speed.
-------------------------
Note: If back slashes are used to escape quotes they can easily be removed
afterwards. Same for leading and trailing spaces.
===============================================================================
Here's something I put together this morning. It allows you to read rows from
your CSV and get values based on the name of the column. This works great when
your header columns are not always in the same order; like when you're
processing many feeds from different customers. Also makes for cleaner, easier
to manage code.
So if your feed looks like this:
product_id,category_name,price,brand_name,
sku_isbn_upc,image_url,landing_url,title,description
123,Test Category,12.50,No Brand,0,http://www.example.com, http://
www.example.com/landing.php, Some Title,Some Description
You can do:
getNext())
{
$dPrice = $o->getPrice();
$nProductID = $o->getProductID();
$sBrandName = $o->getBrandName();
}
?>
If you have any questions or comments regarding this class, they can be
directed to<EMAIL_ADDRESS>as I probably won't be checking back
here.
m_fp = fopen($sFileName, 'r'))
{
$this->processHeader();
}
}
function __call($sMethodName, $saArgs)
{
//check to see if this is a set() or get() request, and extract the
name
if (preg_match("/[sg]et(.*)/", $sMethodName, $saFound))
{
//convert the name portion of the [gs]et to uppercase for
header checking
$sName = strtoupper($saFound[1]);
//see if the entry exists in our named header-> index mapping
if (array_key_exists($sName, $this->m_naHeaderMap))
{
//it does.. so consult the header map for which index
this header controls
$nIndex = $this->m_naHeaderMap[$sName];
if ($sMethodName{0} == 'g')
{
//return the value stored in the index associated
with this name
return $this->m_saValues[$nIndex];
}
else
{
//set the valuw
$this->m_saValues[$nIndex] = $saArgs[0];
return true;
}
}
}
//nothing we control so bail out with a false
return false;
}
//get a nicely formatted header name. This will take product_id and
make
//it PRODUCTID in the header map. So now you won't need to worry
about whether you need
//to do a getProductID, or getproductid, or getProductId.. all will
work.
public static function GetNiceHeaderName($sName)
{
return strtoupper(preg_replace('/[^A-Za-z0-9]/', '', $sName));
}
//process the header entry so we can map our named header fields to a
numerical index, which
//we'll use when we use fgetcsv().
private function processHeader()
{
$sLine = fgets($this->m_fp);
//you'll want to make this configurable
$saFields = split(",", $sLine);
$nIndex = 0;
foreach ($saFields as $sField)
{
//get the nice name to use for "get" and "set".
$sField = trim($sField);
$sNiceName = PaperPear_CSVParser::GetNiceHeaderName($sField);
//track correlation of raw -> nice name so we don't have to do
on-the-fly nice name checks
$this->m_saHeader[$nIndex] = array(C_PPCSV_HEADER_RAW =>
$sField, C_PPCSV_HEADER_NICE => $sNiceName);
$this->m_naHeaderMap[$sNiceName] = $nIndex;
$nIndex++;
}
}
//read the next CSV entry
public function getNext()
{
//this is a basic read, you will likely want to change this to
accomodate what
//you are using for CSV parameters (tabs, encapsulation, etc).
if (($saValues = fgetcsv($this->m_fp)) !== false)
{
$this->m_saValues = $saValues;
return true;
}
return false;
}
}
//quick example of usage
$o = new PaperPear_CSVParser('F:\foo.csv');
while ($o->getNext())
{
echo "Price=" . $o->getPrice() . "\r\n";
}
?>
===============================================================================
The PHP's CSV handling stuff is non-standard and contradicts with RFC4180, thus
fgetcsv() cannot properly deal with files like this example from Wikipedia:
1997,Ford,E350,"ac, abs, moon",3000.00
1999,Chevy,"Venture ""Extended Edition""","",4900.00
1999,Chevy,"Venture ""Extended Edition, Very Large""","",5000.00
1996,Jeep,Grand Cherokee,"MUST SELL!
air, moon roof, loaded",4799.00
Please note: the enclosure symbol is doubled inside fields, field data can
contain linebreaks, and there is no real escape symbol. Also, fputcsv() creates
non-standard CSV files.
There is a quick and dirty RFC-compliant realization of CSV creation and
parsing:
References:
RFC4180 - http://tools.ietf.org/html/rfc4180
Wikipedia - http://en.wikipedia.org/wiki/Comma-separated_values#Example
Also, there is complete solution of CSV handling at http://code.google.com/p/
parsecsv-for-php/
===============================================================================
Currently, I'm working on a script that takes data exported from one database
and converts it so that it can be imported in another. I have been given a
bunch of CSV files containing data to make the translation possible --actually,
the values are semi-colon separated, not comma-separated.
The following script reads a CSV file with field names on the first line (for
an example, see below the script), and turns it into a hash table where the key
is one of the fields.
'')
, $on_collision = ON_COLLISION_ABORT
, $rec_len = 1024
)
{
$handle = fopen($csv_file, 'r');
if($handle == null || ($data = fgetcsv($handle, $rec_len, $separator_input))
=== false)
{
// Couldn't open/read from CSV file.
return -1;
}
$names = array();
foreach($data as $field)
{
$names[] = trim($field);
}
$indexes = array();
foreach($index_by as $index_in => $function)
{
if(is_int($index_in))
{
if($index_in < 0 || $index_in > count($data))
{
// Index out of bounds.
fclose($handle);
return -2;
}
$index_out = $index_in;
}
else
{
// If a column that is used as part of the key to the hash table is
supplied
// as a name rather than as an integer, then determine that named
column's
// integer index in the $names array, because the integer index is
used, below.
$get_index = array_keys($names, $index_in);
$index_out = $get_index[0];
if(is_null($index_out))
{
// A column name was given (as opposed to an integer index), but
the
// name was not found in the first row that was read from the
CSV file.
fclose($handle);
return -3;
}
}
$indexes[$index_out] = $function;
}
if(count($indexes) == 0)
{
// No columns were supplied to index by.
fclose($handle);
return -4;
}
$retval = array();
while(($data = fgetcsv($handle, $rec_len, $separator_input)) !== false)
{
$index_by = '';
foreach($indexes as $index => $function)
{
$index_by .= ($function ? $function($data[$index]) : $data[$index])
. $separator_index;
}
$index_by = substr($index_by, 0, -1);
if(isset($retval[$index_by]))
{
switch($on_collision)
{
case ON_COLLISION_OVERWRITE : $retval[$index_by] =
array_combine($names, $data);
case ON_COLLISION_SKIP : break;
case ON_COLLISION_ABORT : return -5;
}
}
else
{
$retval[$index_by] = array_combine($names, $data);
}
}
fclose($handle);
return $retval;
}
?>
Assume the CSV file DaysOfWeek.csv contains this:
DayNo;DayName;DayAbbr
0;Sunday;Sun
1;Monday;Mon
2;Tuesday;Tue
3;Wednesday;Wed
4;Thursday;Thu
5;Friday;Fri
6;Saturday;Sat
(Reproduced in full as a service to you, dear reader, so you can more easily
test the script if you wish. :-)
Now,
will all read the file, and index it using the contents of the zero'th column
as an index.
Alternatively, you can use the function like this
or like this
Typically, of course, the first index to $days will be a variable rather than a
literal/constant, allowing for easy translation of one value to another.
[EDIT BY danbrown AT php DOT net: Updated by the original poster on 2009-03-06
to fix two typos.]
===============================================================================
If you receive data in the following format:
Time,Dataset1,Dataset2,
timestamp1,item 1 for dataset 1,item1 for dataset2
timestamp2,item 2 for dataset 1,item2 for dataset2
the following code will output a series of arrays grouped by column with the
resulting format:
array (
[column 1 title] => array (
[timestamp1] => item1 for dataset1
[timestamp2] => item2 for dataset1
)
[column 2 title] => array (
[timestamp1] => item1 for dataset2
[timestamp2] => item2 for dataset2
)
)
$value) {
// reparse into useful array data.
if ($key == 0) {
foreach ($value AS $key2=>$value2) {
$array[$key2] = array();
$array[$key2][] = $value2;
}
}else if ($key > 0){
foreach ($value as $key3=>$value3) {
$array[$key3][] = $value3;
}
}else{
}
}
return $array;
}
function groupColumns($array = null) {
$array2 = array();
foreach ($array as $k=>$v) {
// procss each column
// $k = column number
// $v = array of rows
if ($k == 0) {}else{ // working on column 2 or higher
$array2[$v[0]] = array();
foreach ($array[0] as $k1=>$v1) {
if ($v1 > 0) { // ignore the column heading
// store the first column variable in as the key.
// Store the value associated with this item as the value.
$array2[$v[0]][$v1] = $v[$k1];
}
}
}
}
return $array2;
}
$array2 = groupColumns(columnizeArray($csvarray));
print_r($array2);
?>
===============================================================================
You should pay attention to the fact that "fgetcsv" does remove leading
TAB-chars "chr(9)" while reading the file.
This means if you have a chr(9) as the first char in the file and you use
fgetcsv this char is automaticaly deleted.
Example:
file content:
chr(9)first#second#third#fourth
source:
The array $line looks like:
$line[0] = first
$line[1] = second
$line[2] = third
$line[3] = fourth
and not
$line[0] = chr(9)first
$line[1] = second
$line[2] = third
$line[3] = fourth
All chr(9) after another char is not deleted!
Example:
file content:
Achr(9)first#second#third#fourth
source:
The array $line looks like:
$line[0] = Achr(9)first
$line[1] = second
$line[2] = third
$line[3] = fourth
===============================================================================
function to parse multi arrays into csv data
array in... array of array(datasets); first dataset = field names.
usage:
$toparse[0][0] = "field1";
$toparse[0][1] = "field2";
$toparse[1][0] = "value1";
$toparse[1][1] = "123123123"; // to see
echo export_to_csv($toparse);
send the file to the client.. pretty simple.
usage: send_file_to_client("data.csv",export_to_csv($data));
===============================================================================
fgetcsv seems to handle newlines within fields fine. So in fact it is not
reading a line, but keeps reading untill it finds a \n-character that's not
quoted as a field.
Example:
Returns:
array(3) {
[0]=>
string(5) "col 1"
[1]=>
string(4) "col2"
[2]=>
string(4) "col3"
}
array(3) {
[0]=>
string(29) "this
is
having
multiple
lines"
[1]=>
string(8) "this not"
[2]=>
string(13) "this also not"
}
array(3) {
[0]=>
string(13) "normal record"
[1]=>
string(19) "nothing to see here"
[2]=>
string(7) "no data"
}
This means that you can expect fgetcsv to handle newlines within fields fine.
This was not clear from the documentation.
===============================================================================
I had a csv file whose fields included data with line endings (CRLF created by
hitting the carriage returns in html textarea). Of course, the LF in these
fields was escaped by MySQL during the creation of the csv. Problem is I could
NOT get fgetcsv to work correctly here, since each and every LF was regarded as
the end of a line of the csv file, even when it was escaped!
Since what I wanted was to get THE FIRST LINE of the csv file, then count the
number of fields by exploding on all unescaped commas, I had to resort to this:
2){
$srch = substr($srch, 1);//ie trim off the first char
}
if($i > 1 && $srch[1] == chr(10) && $srch[0] != '\\'){//chr(10)
is LF, ie \n
break;//if you get to the \n NOT preceded by \, that's the
real line-ending, stop collecting the string;
}
$i++;
}
echo $str;//should contain the first line as string
?>
Perhaps there exists a more elegant solution to this issue, in which case I'd
be glad to know!
===============================================================================
I used fgetcsv to read pipe-delimited data files, and ran into the following
quirk.
The data file contained data similar to this:
RECNUM|TEXT|COMMENT
1|hi!|some comment
2|"error!|another comment
3|where does this go?|yet another comment
4|the end!"|last comment
I read the file like this:
This causes a problem on record 2: the quote immediately after the pipe causes
the file to be read up to the following quote --in this case, in record 4.
Everything in between was stored in a single element of $row.
In this particular case it is easy to spot, but my script was processing
thousands of records and it took me some time to figure out what went wrong.
The annoying thing is, that there doesn't seem to be an elegant fix. You can't
tell PHP not to use an enclosure --for example, like this:
(Well, you can tell PHP that, but it doesn't work.)
So you'd have to resort to a solution where you use an extremely unlikely
enclosure, but since the enclosure can only be one character long, it may be
hard to find.
Alternatively (and IMNSHO: more elegantly), you can choose to read these files
like this, instead:
As it's more intuitive and resilient, I've decided to favor this 'construct'
over fgetcsv from now on.
===============================================================================
I've had alot of projects recently dealing with csv files, so I created the
following class to read a csv file and return an array of arrays with the
column names as keys. The only requirement is that the 1st row contain the
column headings.
I only wrote it today, so I'll probably expand on it in the near future.
mappings)
$this->mappings = $data;
while($data = fgetcsv($id, filesize($filename)))
{
if($data[0])
{
foreach($data as $key => $value)
$converted_data[$this->mappings[$key]] = addslashes($value);
$table[] = $converted_data; /* put each line into */
} /* its own entry in */
} /* the $table array */
fclose($id); //close file
return $table;
}
}
?>
===============================================================================
Note that fgetcsv() uses the system locale setting to make assumptions about
character encoding.
So if you are trying to process a UTF-8 CSV file on an EUC-JP server (for
example),
you will need to do something like this before you call fgetcsv():
setlocale(LC_ALL, 'ja_JP.UTF8');
[Also not that setlocale() doesn't *permanently* affect the system locale
setting]
===============================================================================
read .csv file (with 1st row = head-row / key-names) .... to assoc array
$heading) {
if (!empty($heading)) { $row[$heading] = (isset($line[$key])) ?
$line[$key] : ''; }
}
if (!empty($row)) { $csvdata[] = $row; }
} else {
if (!empty($line)) { $csvdata[] = $line; }
}
}
// ---------------------
@fclose($ReadHandle);
}
// ----------------------------
return $csvdata;
// --------------------------------------
}
?>
usage / example:
---------------------------------------------------
$res_data1 = csv_to_array($filename1);
$res_data2 = csv_to_array($filename2, true, '|');
$res_data3 = csv_to_array($filename3, true, ';', '"', 2400);
===============================================================================
Method to get table stuckture of CSV as "Columns-Array" and JSON :
Tokyo;New York;Berlin
7.0;-2;0.9
6.9;0.8;0.6
9.5;5.7;-3.5
14.5;11.3;8.4
18.2;17.0;13.5
Output:
Array
(
[Tokyo] => Array
(
[0] => 7
[1] => 6.9
[2] => 9.5
[3] => 14.5
[4] => 18.2
)
[New York] => Array
(
[0] => -2
[1] => 0.8
[2] => 5.7
[3] => 11.3
[4] => 17
)
[Berlin] => Array
(
[0] => 0.9
[1] => 0.6
[2] => -3.5
[3] => 8.4
[4] => 13.5
)
)
{"Tokyo":[7,6.9,9.5,14.5,18.2],"New York":[-2,0.8,5.7,11.3,17],"Berlin":
[0.9,0.6,-3.5,8.4,13.5]}
===============================================================================
NOTE: i think the example in this page should be changed. I think the following
line should be added to just inside the while loop:
if( $data === true ) die('PAY ATTENTION DUMMY');
The reasoning for this, is if the user happens to take out the seemingly
"extra" brackets around the "$data" part, they will get a while bunch of rows
where all they get is the value true instead of an array. This way, if the user
borrows the code but then later on removes the seemingly "extra" brackets, they
have something keeping them safe from themselves at least.
I say this because this just happened to some poorly designed code in a system
I manage, that as a result caused a whole bunch of blank records to be imported
into a database.
===============================================================================
Here is an example how to use this function with generators
https://github.com/luchaninov/csv-file-loader (composer require "luchaninov/
csv-file-loader:1.*")
$loader = new CsvFileLoader();
$loader->setFilename('/path/to/your_data.csv');
foreach ($loader->getItems() as $item) {
var_dump($item); // do something here
}
If you have CSV-file like
id,name,surname
1,Jack,Black
2,John,Doe
you'll get 2 items
['id' => '1', 'name' => 'Jack', 'surname' => 'Black']
['id' => '2', 'name' => 'John', 'surname' => 'Doe']
===============================================================================
I had a problem with multibytes. File was windows-1250, script was UTF-8 and
set_locale wasn't work so I made a simple and safe workaround:
I hope You will find it out usefull.
Sorry for my english.
===============================================================================
For my surprise this function using 5.3.2 on windows now when it reads an empty
line it returns FALSE instead of an empty array as the previous versions. This
affect code that do not check the result and tries something like this:
$value){
// ....
}
}
?>
when it was empty array this foreach pass ok but now with FALSE gives this
error:
Invalid argument supplied for foreach()
Anyways, it is good idea to check what you getting before process further. This
following line will fix the existing code.
if(!$line=fgetcsv($fp,4096,',','"') continue;
===============================================================================
If you have a good idea of the max length of the line you're importing, it's a
very good idea to enter the "optional" length parameter.
You may be very pleasantly surprised. (In my recent experience(YMMV), from an
hour down to 21 seconds!)
===============================================================================
If you don't want to define an enclosure charachter you can do the following:
I needed this to detect the enclosure used for csv files.
===============================================================================
If you want to get your CSV rows (in this case a file posted from a form) into
one big array, you can use this code. You may have to play around with the ord
() and explode separators depending on your line endings. You can change to
the commented out explode to use " delimiter.
===============================================================================
I was getting a bytes exhausted error when iterating through a CSV file.
ini_set('auto_detect_line_endings', 1); fixed it.
===============================================================================
Another version [modified michael from mediaconcepts]
===============================================================================
fgetcsv stops reading your file?
I had to write a script to validate and import a large amount of data to MySQL
and it would stop running. I've noticed, after trawling the internet for a
solution, quite a few people have had similar problems.
Solution? Like a dope I had forgotten to put in
set_time_limit()
within a loop. Otherwise the script would time out before it finished importing
all the data.
Moral of the story? Only suppress errors after your script works with a large
amount of test data!
===============================================================================
This function takes a csv line and splits it into an array, much like fgetcsv
does but you can use it on data that isn't coming in from a file, or you can
read data from a file some other way (like if your Mac files aren't being read
correctly) and use this to split it. If you have any corrections, comments
(good or bad), etc. I would appreciate an email to the above address.
===============================================================================
This function appears to assume that \" is an escaped quote - similar to "" -
which may lead to incorrect results while reading some files. Found while
running under PHP 5.1.6.
===============================================================================
// ---------------------------------------------------------------
function csv_get_array($csvfile, $csvhead=true, $delimiter=";", $enclosure="\
"", $rowlength=0) {
$csvdata = array();
if (file_exists($csvfile)) {
$ReadHandle = fopen($csvfile, 'r');
if ($csvhead === true) {
$headrow = fgetcsv($ReadHandle, $rowlength, $delimiter, $enclosure);
}
while($line = fgetcsv($ReadHandle, $length, $delimiter, $enclosure)) {
if ($csvhead === true) {
foreach ($headrow as $key => $heading) {
if (!empty($heading)) {
$row[$heading] = (isset($line[$key])) ? $line[$key] : '';
}
}
if (!empty($row)) { $csvdata[] = $row; }
}
else {
if (!empty($line)) { $csvdata[] = $line; }
}
}
fclose($ReadHandle);
}
return $csvdata;
}
// ---------------------------------------------------------------
===============================================================================
If anyone else is taking on the task of converting from FileMaker Pro to MySQL,
you might find this useful:
Here's a collection of simple functions that take a CSV file, re-formats the
data and writes to a file with MySQL INSERTs.
ORIGINAL DATA:
"1", "foo", "2"
"3", "bar", "4"
OUTPUT
INSERT info mysql_table VALUES('', '1', 'foo', '2');
INSERT info mysql_table VALUES('', '3', 'bar', '4');
For simple data it works alright, but I could not find a way to escape the
contents before assembling the INSERT statements - kept getting "bad argument
for implode()"...
";
$row++;
}
fclose ($f);
return $dump;
}
function makeINSERT($text, $table){
$insert = array();
$i = 0;
while (list($key, $val) = @each($text)){
// We'll start off the INSERT with '', for an
// auto-incremented key. Remove if not needed.
$insert[$i] = "INSERT into ".$table." VALUES('','";
$insert[$i] .= implode("','", $val);
$insert[$i] .= "');\n";
$i++;
}
return $insert;
}
?>
===============================================================================
Here is a simple to include the field names in the array. Altough this is very
simple, it does the job fantastically
===============================================================================
There is still a bug with column headings ( "false" != false )
$value) {
unset($data[$key]);
$data[$headingTexts[$key]] = $value;
}
$rows[] = $data;
} else {
$rows[] = $data;
}
$row++;
}
fclose($handle);
return $rows;
}
?>
===============================================================================
The following modification will hide the unnecessary delimiter in the array
that is returned when fgetcsvfromline is called.
=== If you were getting
[0] => "Ma"rk","Bergeron","rocks","12345,"times"
[1] => "
[2] => Ma"rk
[3] => "
..etc
You will now get
[0] => "Ma"rk","Bergeron","rocks","12345,"times"
[1] => Ma"rk
...etc
===============================================================================
beware of using this function in two different php versions,
in php 4.3 the 4th parameter can be given altough empty
in php 4.2 you get just a warning but it is not able to read the csv file if
you place an enclosure that is empty
===============================================================================
A 5.2 way to lazily parse a single CSV line
===============================================================================
Important note about the CSV format:
There should *not* be any space in between the fields. For example,
field1, field2, field3 [Wrong!]
field1,field2,field3 [Correct-No space between fields]
If you add space between the fields, MS Excel won't recognize the fields
(especially date and multi-line text fields).
HTH,
R. Rajesh Jeba Anbiah
===============================================================================
Here is a function that takes an array and adds a CSV line to the passed file
pointer.
[EDIT BY danbrown AT php DOT net: A function named fputcsv(), performing a very
similar action, was added to the core in PHP 5.1.0.]
===============================================================================
For anyone else struggling with disappearing non-latin characters in one-byte
encodings - setting LANG env var (as the manual states) does not help at all.
Look at LC_ALL instead.
In my case it was set to "pl_PL.utf8" but since my input file was in CP1250
most of polish characters (but not all of them!) had gone missing and city of
"Łódź" had become just "dź". I've "fixed" it with "pl_PL".
===============================================================================
If you want to load some translations for your application, don't use csv files
for that, even if it's easier to handle.
The following code snippet:
is about 400% slower than this code:
$val)
{
$lang[$key] = $val;
}
?>
That's the reason why you should allways use .ini files for translations...
http://php.net/parse_ini_file
===============================================================================
I modified the code for my own purposes, to return an array with named keys for
each field. I tried various alternatives, and this seems to work well with
exported Excel data.
Jon Hassall
===============================================================================
I was using the function to import a csv file that had some values with "\"
included this confused the import function to ignore the End of line and hence
an incorrect number of rows is returned to me.
Suggest you try to replace that \ and { brackets as well since they have the
same function of an escape character before u import the function
thanks
===============================================================================
The file function reads the file in an array with the EOL still attached, so
the +1 is not necessary.
===============================================================================
using the example above with a length of 1000 will truncate any csv rows longer
than 1000 bytes, the remainder of that line will be represented next time you
call $data = fgetcsv(). one solution i have seen to this is to use filesize
("test.csv") as the length argument, however sometimes with large csv files you
may encounter errors for exceeding the memory limit. to remedy this, i have
read the csv file into an array, looping through that array to find the longest
line in the csv, and then using that value as my length argument, unset($array)
to free up the memory. im open to better solutions.
===============================================================================
The fgetcsv() is really great. CSV files are not as simple as they seem. They
may span multiple lines, contain unmatched double quotes (like: 32" screen
size) and lot of other surprising variants. My problem was that I had an
ISO-8859-1 encoded file and fgetcsv() expects it to be UTF-8 encoded. I tried
with a range of regular expressions I found on the Internet but none of them
worked 100 %. So, if you haven't discovered it yet: fgetcsv() is king. My
server doesn't have str_getcsv() so I had to figure out some way to use fgetcsv
() for my ISO-8859-1 files.
I found the answer here: http://bugs.php.net/bug.php?id=48507. So I ended up
with:
data = utf8_encode($bucket->data);
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
?>
and


Writing a neural networking framework in Python imposes certain speed restrictions upon it. Python is just not as fast as languages such as C++ or Fortran.
Due to this, PyBrain has its own spin-off called arac, which is a re-implementation of its neural networking facilities that integrates transparently with it.
Depending on the configuration of your system, speedups of 5-10x faster can be expected. This speedup might be even higher (ranging into the hundreds) if you use sophisticated topologies such as MDRNNs. If you want some numbers on your system, there is a comparison script shipped with PyBrain at examples/arac/benchmark.py.
However, the installation process is less easy than for pure Python PyBrain. On the other hand, it’s mostly about installing an additional library and telling PyBrain to use fast networks.
You will find detailed installation instructions for arac on the arac wiki.
This instructions are work in progress. If you run into difficulties, ask on the PyBrain mailing list.
Once you have installed it, there are three ways to use fast networks.
First, the shortcut buildNetwork has a keyword fast which builds an arac network instead:
>>> from pybrain.tools.shortcuts import buildNetwork
>>> n = buildNetwork(2, 3, 1, fast=True)
>>> n.activate((2, 3))
array([-0.20781205])
As you can see by examining the network, it is a special class:
>>> n
<_FeedForwardNetwork '_FeedForwardNetwork-8'>
which is prefixed with an underscore, the Python convention for naming C implementations of already existing classes. We can import these classes directly from arac and use them in the same way as PyBrain classes:
>>> from arac.pybrainbridge import _FeedForwardNetwork, _RecurrentNetwork
The third method is to construct a network as a PyBrain network and call the method convertToFastNetwork afterwards:
>>> n = buildNetwork(2, 3, 1, fast=False)
>>> n.convertToFastNetwork()
<_FeedForwardNetwork '_FeedForwardNetwork-18'>
However, be cautious with the last method since changes to the PyBrain network are not reflected in the arac network.
Since arac is implemented in C++ and currently maintained by only a single person, arac development is likely to be slower than PyBrain’s. This might lead to certain features (e.g. layer types) to be implemented later than the pure python versions. This also applies to custom layer types. As soon as you have your layer type, you will not be able to use fast networks anymore – except if you chose to also implement them for arac yourself.


March-June 2022
Helping customers reach all of their security goals and needs in one centralized place.
A project created to inspire future state thinking for Verizon’s consolidated user security dashboard. We designed 3 main experiences: smart setup, dashboard, and a “wrap report” for this future state pitch deck. This case study focuses on the account holder’s smart setup experience.
Within the Verizon ecosystem, there are dozens of apps for their customers. The client was looking to create a centralized dashboard for users to setup, view and manage all of their security settings. Over the months, we helped design a setup experience, dashboard experience, as well as an experience to view overall security stats and ratings based on your profile.
The client was looking for a dashboard and an easy way for users to set up their security settings.
Before starting this project, we took a step back to look at overarching themes to help guide our designs. Key findings were that copy needed to be minimal and easy to understand, the experience needed to be customized to fit the user’s needs and there needed to be transparency between each step so the user felt engaged during the process.
I researched existing security platforms, as well as other mobile apps that used similar interaction patterns for quizzes and smart setup experiences. Here are some of the very initial sketches I created.
The smart setup would consist of
* an introduction
* a series of questions to customize the primary user’s experience
* a transparent automated profile setup
* confirmation of the profile and settings
A very basic low-fidelity flow for this experience.
I iterated on the screens for many months. Every week I presented designs to the client for feedback. Over the months, new requirements appeared and the amount of flows grew exponentially.
The final smart setup flow consisted of three distinct portions:
* Creating profiles for all account users
* Setting up all personal and work devices and placing each device into a group (to optimize security settings)
* Applying security settings to all of these devices
Given time restraints and lack of data for security settings, we were only able to design the first two portions of this smart setup process. Overall, this process was challenging because it involved bringing together several incoherent experiences. This meant talking to various stakeholders and trying to convince them to get onboard with this unified vision.


Basic Tutorial
In this first tutorial, we will got through all the main features of the cdt package:
Loading a dataset
Recovering a graph skeleton with independence tests
Apply a causal Discovery algorithm
Evaluate our approach using 3 different scoring metrics
1. Load data
Loading a standard dataset using the cdt package is straightforward using the
cdt.data
module. In this
tutorial, we are going to load the Sachs dataset.
See also
Sachs, K., Perez, O., Pe’er, D., Lauffenburger, D. A., & Nolan, G. P. (2005). Causal protein-signaling networks derived from multiparameter single-cell data. Science, 308(5721), 523-529.
 Graph skeleton
Having a graph skeleton on given data might be quite useful for having information on the structure of the data. In order to do so, let’s apply the Graph Lasso.
See also
Friedman, J., Hastie, T., & Tibshirani, R. (2008). Sparse inverse covariance estimation with the graphical lasso. Biostatistics, 9(3), 432-441:
>>> glasso = cdt.independence.graph.Glasso()
>>> skeleton = glasso.predict(data)
>>> print(skeleton)
<networkx.classes.digraph.DiGraph at 0x7fe3ccfb1438>
The skeleton
object is a networkx.Graph
instance, which might be quite
obscure at first but is handy in the long run. (Check
here for a quick introduction on networkx
graphs).
We can check the structure of the skeleton by looking at its adjacency matrix:
>>> print(nx.adjacency_matrix(skeleton).todense())
matrix([[ 9.26744031e-04, -6.13751618e-04, 1.66612981e-05,
-1.10912131e-06, -3.04172363e-05, -9.71526466e-05,
7.00340545e-05, -1.93863471e-06, -7.31774543e-06,
2.29788237e-06, 8.31264711e-06],
[-6.13751618e-04, 4.14978956e-04, -1.37962487e-05,
1.42164753e-06, 2.04443539e-05, 8.24208108e-05,
-5.63238668e-05, 1.62688021e-06, 8.63444133e-06,
-2.88779755e-06, -4.69605195e-06],
[ 1.66612981e-05, -1.37962487e-05, 2.60824802e-04,
-1.35895911e-04, 8.78979413e-05, 2.17234579e-05,
-2.07856535e-05, 1.23313600e-06, 2.12954874e-05,
-3.22869246e-06, -7.47522248e-06],
[-1.10912131e-06, 1.42164753e-06, -1.35895911e-04,
8.68622146e-05, -7.05405720e-05, 3.08709259e-06,
-2.60810094e-06, 9.09261370e-09, -6.25320515e-06,
2.56399675e-07, 2.85201875e-07],
[-3.04172363e-05, 2.04443539e-05, 8.78979413e-05,
-7.05405720e-05, 6.09681818e-04, -9.91703900e-06,
1.78188074e-05, -5.97491176e-07, 6.11896719e-06,
-4.30918870e-07, 5.79322379e-06],
[-9.71526466e-05, 8.24208108e-05, 2.17234579e-05,
3.08709259e-06, -9.91703900e-06, 1.10860610e-03,
-3.08483289e-04, -1.30867663e-05, -3.31258890e-05,
7.76132824e-06, 2.10416319e-05],
[ 7.00340545e-05, -5.63238668e-05, -2.07856535e-05,
-2.60810094e-06, 1.78188074e-05, -3.08483289e-04,
1.66144775e-04, 1.26667898e-06, 3.11407736e-05,
-7.29116898e-06, -1.86454298e-05],
[-1.93863471e-06, 1.62688021e-06, 1.23313600e-06,
9.09261370e-09, -5.97491176e-07, -1.30867663e-05,
1.26667898e-06, 2.80073467e-06, -3.78879972e-06,
8.67580852e-07, 6.92379671e-07],
[-7.31774543e-06, 8.63444133e-06, 2.12954874e-05,
-6.25320515e-06, 6.11896719e-06, -3.31258890e-05,
3.11407736e-05, -3.78879972e-06, 1.59642510e-03,
-2.58155157e-04, -1.01767664e-04],
[ 2.29788237e-06, -2.88779755e-06, -3.22869246e-06,
2.56399675e-07, -4.30918870e-07, 7.76132824e-06,
-7.29116898e-06, 8.67580852e-07, -2.58155157e-04,
5.32997159e-05, -3.35285721e-06],
[ 8.31264711e-06, -4.69605195e-06, -7.47522248e-06,
2.85201875e-07, 5.79322379e-06, 2.10416319e-05,
-1.86454298e-05, 6.92379671e-07, -1.01767664e-04,
-3.35285721e-06, 7.05796078e-05]])
As you have noticed already, the graph is quite dense. Let’s remove indirect links in the graph using the Aracne algorithm
See also
An Algorithm for the Reconstruction of Gene Regulatory Networks in a Mammalian Cellular Context Adam A Margolin, Ilya Nemenman, Katia Basso, Chris Wiggins, Gustavo Stolovitzky, Riccardo Dalla Favera and Andrea Califano DOI: https://doi.org/10.1186/1471-2105-7-S1-S7
>>> new_skeleton = cdt.utils.graph.remove_indirect_links(skeleton, alg='aracne')
>>> print(nx.adjacency_matrix(new_skeleton).todense())
matrix([[9.26576364e-04, 0.00000000e+00, 1.66279016e-05, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 6.99676073e-05, 0.00000000e+00,
0.00000000e+00, 2.26182196e-06, 8.29822467e-06],
[0.00000000e+00, 4.14897907e-04, 0.00000000e+00, 0.00000000e+00,
2.04095344e-05, 8.22844158e-05, 0.00000000e+00, 1.62835373e-06,
8.48527014e-06, 0.00000000e+00, 0.00000000e+00],
[1.66279016e-05, 0.00000000e+00, 2.60808178e-04, 0.00000000e+00,
8.78753504e-05, 2.17299267e-05, 0.00000000e+00, 1.23340219e-06,
2.12217433e-05, 0.00000000e+00, 0.00000000e+00],
[0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 8.68568259e-05,
0.00000000e+00, 3.07901285e-06, 0.00000000e+00, 8.94955462e-09,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[0.00000000e+00, 2.04095344e-05, 8.78753504e-05, 0.00000000e+00,
6.09654932e-04, 0.00000000e+00, 1.77984674e-05, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 5.80118715e-06],
[0.00000000e+00, 8.22844158e-05, 2.17299267e-05, 3.07901285e-06,
0.00000000e+00, 1.10847276e-03, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 7.72649753e-06, 2.10224309e-05],
[6.99676073e-05, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
1.77984674e-05, 0.00000000e+00, 1.66117739e-04, 1.26646124e-06,
3.10736844e-05, 0.00000000e+00, 0.00000000e+00],
[0.00000000e+00, 1.62835373e-06, 1.23340219e-06, 8.94955462e-09,
0.00000000e+00, 0.00000000e+00, 1.26646124e-06, 2.80075082e-06,
0.00000000e+00, 8.67949681e-07, 6.92548597e-07],
[0.00000000e+00, 8.48527014e-06, 2.12217433e-05, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 3.10736844e-05, 0.00000000e+00,
1.59628546e-03, 0.00000000e+00, 0.00000000e+00],
[2.26182196e-06, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 7.72649753e-06, 0.00000000e+00, 8.67949681e-07,
0.00000000e+00, 5.32959890e-05, 0.00000000e+00],
[8.29822467e-06, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
5.80118715e-06, 2.10224309e-05, 0.00000000e+00, 6.92548597e-07,
0.00000000e+00, 0.00000000e+00, 7.05766621e-05]])
and the resulting skeleton is much more sparse. Let’s build on this new skeleton to perform our causal discovery.
3. Causal discovery
Having a graph skeleton, we are going to perform causal discovery with constraints, by using the GES algorithm.
See also
D.M. Chickering (2002). Optimal structure identification with greedy search. Journal of Machine Learning Research 3 , 507–554
>>> model = cdt.causality.graph.GES()
>>> output_graph = model.predict(data, new_skeleton)
>>> print(nx.adjacency_matrix(output_graph).todense())
matrix([[0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1],
[1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int64)
And we obtain GES’s prediction on this graph using the skeleton as constraint. Next we are going to evaluate our solution compared to using CAM without skeleton.
See also
J. Peters, J. Mooij, D. Janzing, B. Schölkopf: Causal Discovery with Continuous Additive Noise Models, JMLR 15:2009-2053, 2014.
4. Evaluation and scoring metrics
In order to evaluate various predictions with the ground truth, the cdt
package includes 3 different metrics in the cdt.metrics
module:
Area under the precision recall curve
Structural Hamming Distance (SHD)
Structural Intervention Distance (SID)
>>> from cdt.metrics import (precision_recall, SID, SHD)
>>> scores = [metric(graph, output_graph) for metric in (precision_recall, SID, SHD)]
>>> print(scores)
[(0.3212943387361992, [(0.1487603305785124, 1.0), (0.16279069767441862, 0.3888888888888889), (1.0, 0.0)]),
array(76.),
47]
>>> # now we compute the CAM graph without constraints and the associated scores
>>> model2 = cdt.causality.graph.CAM()
>>> output_graph_nc = model2.predict(data)
>>> scores_nc = [metric(graph, output_graph_nc) for metric in (precision_recall, SID, SHD)]
>>> print(scores_nc)
[(0.4423624964377315, [(0.1487603305785124, 1.0), (0.3103448275862069, 0.5), (1.0, 0.0)]),
array(68.),
29]
We can observe that CAM has better performance than our previous pipeline, as:
The average precision score is higher
The SID score is lower
The SHD score is lower as well
This concludes our first tutorial on the cdt package.


Expression
Pretty print
$$$$
Result
-->
LaTeX of what you typed:
Type your equation here:
Command to run:
python criticalpoints.py -e
f
-a 40
inside of the folder
sin(x)
In the case of
, the common solutions are as follows:
Invertable region domains
Invertable domain:
All possible domains equations (n=N)
x1 =
x2 =
Other Solutions
Periodicity:
Inverse Equation:
Simplified Equation:
Angle Solutions
Quadrant of Unit Circle: Quadrant #


Property Pages Settings preferences
Use the Property Pages Settings preference panel to set the behaviors of CDT property pages.
| Option | Description |
|---|---|
| Show 'Manage Configurations...' button | Shows or hides corresponding button, normally placed on every property page. If this button is hidden, Manage operation can be accessed from Main Menu or Context Menu. |
| Display 'Include Files' tab | Displays a tab under 'Paths & Symbols' showing files which are included by default. These included files will be parsed before source, even if they're not explicitly #include'd by the source file. Corresponds to the '-include' switch on GNU compilers. |
| Display 'Data hierarchy' tab | Displays auxiliary tab which allows browsing data of project configurations. This feature is useful for debug purposes mostly, so it's disabled by default. |
| Display tool option tips of 'Tool Settings' tab at fixed location | |
| Display 'Tool Chain Editor' tab | Shows or hides corresponding tab. Normally, users need not to edit tool chains manually. |
| Save Property Dialog Bounds | Defines how property dialog parameters are preserved:
|
| Discovery Profiles Naming Rule | Discovery profiles have unique IDs, but their names may be duplicate,
especially if they are contributed by different developers. So there
are 4 way to distinguish them in the list on Discovery tab:
|


I'm a computer science engineer with five years of commercial experience and academic in the areas of software development and data science. My educational output deals with Machine Learning, Data Mining, Deep neural nets, Text Analytics and Metaheuristics. Outside of academia, I spent three years developing and managing iPad software application at Tata Consultancy Services (client Novo Nordisk) as a Systems Engineer. Later in the academia, as a teaching assistant, I have mentored over 200+ students on topics associated with data analysis in R and python.
Now, I have been working as a research assistant at Systems realization laboratory, OU. As a data scientist, my work includes data collection, data wrangling, automation of text extraction from word documents, feature engineering, modeling the data and deploying all these modules into a web application to analyze the student’s learning. Further used big data computation platforms like HDFS, Apache Ambari, and Apache Spark in different projects.
I am passionate about data and would be helpful to your team keen in building and deploying models. Will bring in communication, ML programming skills and curiosity to the data science problem at hand. I can pick up an unfamiliar domain, and an implementor of continuous learning through back-propagation.
Machine Learning, Data Analysis, Statistical Modeling, SQL
Data Mining - Association, Anamoly Detection
Deep Learning - CNN, LSTM, GAN's, Word Embedding (Word2Vec)
NLP - LDA, text classification & clustering
Hadoop Ecosystem, Mapreduce, HDFS, Hive, Apache Spark, Apache Ambari, mongodb
Amazon Web Services (AWS) – EC2, S3
Python, R caret, Scikit-Learn, keras, Tensorflow, SAS
Tableau 10.5, R Shiny, Neo4j, D3.js
Objective-C, Java, C++


The best way to familiarise yourself with OpenCOR's internals is by having a look at its source code.
All of OpenCOR's code is and must be made available under the OpenCOR
namespace (e.g. [OpenCOR]/src/mainwindow.cpp
and [OpenCOR]/src/mainwindow.h
). There are two exceptions to this rule: [OpenCOR]/src/main.cpp
and [OpenCOR]/windows/src/main.cpp
(i.e. OpenCOR's two main .cpp
files).
All changes to OpenCOR's codebase must be referenced in the list of issues using labels. There are three types of labels:
Whenever something is pushed to our Git repository, OpenCOR gets automatically built and tested on Travis CI's Ubuntu and OS X machines. That is, unless [ci skip]
has been added to a commit comment. However, and as a general rule, a commit that closes an issue should always trigger OpenCOR to be built and tested on Travis CI.
More specific information can be found in the following pages:


by Jason Lengstorf
@jlengstorf |<EMAIL_ADDRESS>Slides: git.io/vyzvq
(s → a) → ((a, s) → s) → Lens s a
Lens s a = Functor f => (a → f a) → s → f s
(If you do understand this, now would be a good time to fake an urgent phone call.)
var xLens = R.lens(R.prop('x'), R.assoc('x'));
R.view(xLens, {x: 1, y: 2}); //=> 1
R.set(xLens, 4, {x: 1, y: 2}); //=> {x: 4, y: 2}
R.over(xLens, R.negate, {x: 1, y: 2}); //=> {x: -1, y: 2}
const people = [
{
name: 'Marisa',
spirit_animal: 'koala',
beverages: [
'tea',
'vodka', // <-- WTF is this?!
],
},
{
name: 'Jason',
spirit_animal: 'bear',
beverages: [
'coffee',
'whiskey',
],
},
];
First: a quick bit of
jargon vocabulary.
Code that explicitly describes how to do something.
"I'd like the pie heated and I don't want the ice cream on top, I want
it on the side, and I'd like strawberry instead of vanilla if you have
it. If not, then no ice cream, just whipped cream — but only if it's
real; if it's out of the can then nothing."
Code that describes what the result should be.
"Give me all the bacon and eggs you have."
Let’s look at some code to fix that beverage list.
let fixed = [];
for (let person of people) {
if (person.beverages) {
for (let beverage in person.beverages) {
if (person.beverages[beverage] === 'vodka') {
person.beverages[beverage] = 'whiskey (FTFY)';
}
}
}
fixed.push(person);
}
Try this live: https://goo.gl/aobHwP
const fixBeverage = (str) => (
str.replace('vodka', 'whiskey (FTFY)')
);
const helpIfConfused = (person) => ({
...person,
beverages: person.beverages.map(fixBeverage)
});
const fixed = people.map(helpIfConfused);
Try this live: https://goo.gl/HO7tps
[
{
"name": "Marisa",
"spirit_animal": "koala",
"beverages": [
"tea",
"whiskey (FTFY)"
]
},
{
"name": "Jason",
"spirit_animal": "bear",
"beverages": [
"coffee",
"whiskey"
]
}
]
Array.prototype.map()
Applies a function to each element of an array.
const double = num => num * 2;
const numbers = [1, 2, 3];
const nextNumbers = [];
for (let x in numbers) {
nextNumbers[x] = double(numbers[x]);
}
Try this live: https://goo.gl/30SfNQ
const double = num => num * 2;
const numbers = [1, 2, 3];
const nextNumbers = numbers.map(double);
Try this live: https://goo.gl/7mYn2x
Array.prototype.filter()
Array.prototype.sort()
Array.prototype.every()
let myFavoriteThing = 'whiskey';
function describeMyFavoriteThing() {
return `I prefer to drink quality ${myFavoriteThing}.`;
}
Try this live: https://goo.gl/IQeD45
function clarifyFavoriteThing() {
myFavoriteThing = 'aged ' + myFavoriteThing;
}
Try this live: https://goo.gl/FEUtUZ
function makeFamilyFriendly() {
myFavoriteThing = 'scented bubble bath';
}
Try this live: https://goo.gl/zgRpEm
let myFavoriteThing = 'whiskey';
clarifyFavoriteThing();
describeMyFavoriteThing();
//=>"I prefer to drink quality aged whiskey." (yay!)
// ...probably a bunch of additional code...
makeFamilyFriendly();
// ...probably more additional code...
describeMyFavoriteThing();
//=>"I prefer to drink quality scented bubble bath." (!)
Try this live: https://goo.gl/xFPtJF
function describeMyFavoriteThing(beverage) {
return `I prefer to drink quality ${beverage}.`;
}
function clarifyFavoriteThing(favoriteThing) {
return `aged ${favoriteThing}`;
}
function makeFamilyFriendly() {
return 'scented bubble bath';
}
Try this live: https://goo.gl/qDtJeu
const myFavoriteThing = 'whiskey';
const clarified = clarifyFavoriteThing(myFavoriteThing);
const newFavorite = makeFamilyFriendly();
describeMyFavoriteThing(myFavoriteThing);
//=>"I prefer to drink quality whiskey."
describeMyFavoriteThing(clarified);
//=>"I prefer to drink quality aged whiskey."
describeMyFavoriteThing(newFavorite);
//=>"I prefer to drink quality scented bubble bath."
Try this live: https://goo.gl/qDtJeu
// start debugging here: ↓ ↓ ↓ ↓ ↓
describeMyFavoriteThing(newFavorite);
Try this live: https://goo.gl/qDtJeu
This means the function call can always be replaced with its return value without breaking the program.
const chz = `I love ${clarifyFavoriteThing('cheddar')}`;
...is the same as...
const chz = 'I love aged cheddar.';
expect(clarifyFavoriteThing('cheddar'))
.toEqual('aged cheddar');
function describeMyFavoriteThing(beverage) {
return `I prefer to drink quality ${beverage}.`;
}
function clarifyFavoriteThing(favoriteThing) {
return `aged ${favoriteThing}`;
}
const showClarifiedFavorite = R.compose(
describeMyFavoriteThing,
clarifyFavoriteThing
);
const result = showClarifiedFavorite('whiskey');
Try this live:https://goo.gl/wQFhZK
describeMyFavoriteThing(clarifyFavoriteThing('whiskey'));
It just means we don't need the data up front.
const albums = [
{
name: 'Middle Cyclone',
artist: 'Neko Case',
genre: 'indie',
},
{
name: 'Highly Refined Pirates',
artist: 'Minus The Bear',
genre: 'rock',
},
{
name: 'Rabbit Fur Coat',
artist: 'Jenny Lewis',
genre: 'indie',
},
{
name: 'Black on Both Sides',
artist: 'Mos Def',
genre: 'hip-hop',
},
];
function getOnlyIndie(albums) {
let filtered = [];
for (let album of albums) {
if (album.genre === 'indie') {
filtered.push(album);
}
}
filtered.sort((album1, album2) => {
if (album1.artist === album2.artist) return 0;
return album1.artist > album2.artist ? 1 : -1;
});
return filtered;
}
Try this live: https://goo.gl/lPK1CD
const byArtistAsc = (album1, album2) => {
if (album1.artist === album2.artist) {
return 0;
}
return album1.artist > album2.artist ? 1 : -1;
};
const getOnlyIndie = album => album.genre === 'indie';
albums.filter(getOnlyIndie).sort(byArtistAsc);
Try this live: https://goo.gl/HXscSK
We can do even better.
const filterByGenre = R.curry((genre, album) => {
return album.genre === genre;
});
// Create similar functions without duplicate code
const onlyHipHop = filterByGenre('hip-hop');
const onlyIndie = filterByGenre('indie');
const onlyRock = filterByGenre('rock');
const hipHop = albums.filter(onlyHipHop);
Try this live: https://goo.gl/qPJhZW
R.curry()
Allows functions to be called in stages.
function addNumbers(num1, num2) {
return num1 + num2;
}
const curriedAdd = R.curry(addNumbers);
const add4 = curriedAdd(4);
add4(2); //=> 6
add4(7); //=> 11
Try this live: https://goo.gl/jVjOW3
...but just these three techniques will save you hours of headaches and make your code better and easier to deal with going forward.
Jason Lengstorf
@jlengstorf |<EMAIL_ADDRESS>Tweet: @jlengstorf #webrebels


Jayaho provides an interactive online learning platform where students can enjoy and learn over the internet, using a real-time virtual learning environment..
Cost: $5
Cost: $10
Cost: $15
Cost: $20


Synology for their awesome devices.
SynoCommunity for making it super easy to package software for Synology's package center.
German Synology wiki for their documentation. Synology's developer documentation is a bit sparse and sometimes incomplete.
Remco Schellekens (Merty) I've used the Config File Editor package as a reference to implement the GUI.
And of course Frank Denis (@jedisct1) for making dnscrypt-proxy and creating the dnscrypt protocol. Without him this package would not be possible.
Big thanks to the many open and free DNS server operators. Without them none of this would work.
Extra thanks to @Safihre and @ymartin59 for their patience and reviewing my commits. And finally thanks to @zenofx for your Linux knowledge.


- A
- D
- T
- U
Add user to project with passed access role by user id
Source: show
# File app/roles/team.rb, line 26 def add_user_id_to_team(user_id, access_role) users_projects.create( user_id: user_id, project_access: access_role ) end
Add user to project with passed access role
Source: show
# File app/roles/team.rb, line 14 def add_user_to_team(user, access_role) add_user_id_to_team(user.id, access_role) end
Add multiple users to project with same access role by user ids
Source: show
# File app/roles/team.rb, line 35 def add_users_ids_to_team(users_ids, access_role) UsersProject.bulk_import(self, users_ids, access_role) end
Add multiple users to project with same access role
Source: show
# File app/roles/team.rb, line 20 def add_users_to_team(users, access_role) add_users_ids_to_team(users.map(&:id), access_role) end
Delete multiple users from project by user ids
Source: show
# File app/roles/team.rb, line 46 def delete_users_ids_from_team(users_ids) UsersProject.bulk_delete(self, users_ids) end
Get Team Member record by user id
Source: show
# File app/roles/team.rb, line 8 def team_member_by_id(user_id) users_projects.find_by_user_id(user_id) end
Source: show
# File app/roles/team.rb, line 2 def team_member_by_name_or_email(name = nil, email = nil) user = users.where("name like ? or email like ?", name, email).first users_projects.where(user: user) if user end


One life I'm gonna live it up I'm takin' flight said I'll never get enough.
Stand tall I'm young and kinda proud I'm on top as long as the music's loud.

Out there is a fortune waitin' to be had If you think I'll let it go you're mad
You've got another thing comin'.
That's right here's where the talkin' ends
Well listen this night there'll be some action spent.
Drive hard I'm callin' all the shots I got an ace card comin' down on the rocks.
If you think I'll sit around while you chip away my brain
Listen I ain't foolin' and you'd better think again.
Out there is a fortune waitin' to be had If you think I'll let it go you're mad
You've got another thing comin'.
In this world we're livin' in we have our share of sorrow
Answer now is don't give in aim for a new tomorrow.
Oh so hot no time to take a rest yeah Act tough ain't room for second best.
Real strong got me some security Hey I'm a big smash I'm goin' for infinity yeah.

Out there is a fortune waitin' to be had If you think I'll let it go you're mad
You've got another thing comin'.
You've got another thing comin'.
You've got another thing comin'.